From 76e30aa7ed477b9720f2c483a6bed141aa381b3d Mon Sep 17 00:00:00 2001 From: Darief Maes Date: Mon, 6 Apr 2026 17:50:24 -0400 Subject: [PATCH 1/3] profiling of times --- .../fmsr_chiller_failure_modes_run_-1.json | 21 + .../fmsr_chiller_failure_modes_run_-2.json | 21 + .../fmsr_chiller_failure_modes_run_01.json | 21 + .../fmsr_chiller_failure_modes_run_02.json | 21 + .../fmsr_chiller_failure_modes_run_03.json | 21 + .../fmsr_chiller_failure_modes_run_04.json | 21 + .../fmsr_chiller_failure_modes_run_05.json | 21 + .../timing/runs/iot_assets_main_run_-1.json | 21 + .../timing/runs/iot_assets_main_run_-2.json | 21 + .../timing/runs/iot_assets_main_run_01.json | 23 + .../timing/runs/iot_assets_main_run_02.json | 23 + .../timing/runs/iot_assets_main_run_03.json | 23 + .../timing/runs/iot_assets_main_run_04.json | 21 + .../timing/runs/iot_assets_main_run_05.json | 21 + .../runs/iot_assets_main_warmup_01.json | 23 + .../runs/iot_observations_ch1_run_-1.json | 21 + .../runs/iot_observations_ch1_run_-2.json | 21 + .../runs/iot_observations_ch1_run_01.json | 21 + .../runs/iot_observations_ch1_run_02.json | 21 + .../runs/iot_observations_ch1_run_03.json | 21 + .../runs/iot_observations_ch1_run_04.json | 21 + .../runs/iot_observations_ch1_run_05.json | 21 + .../runs/iot_sensors_chiller_1_run_-1.json | 21 + .../runs/iot_sensors_chiller_1_run_-2.json | 21 + .../runs/iot_sensors_chiller_1_run_01.json | 21 + .../runs/iot_sensors_chiller_1_run_02.json | 21 + .../runs/iot_sensors_chiller_1_run_03.json | 21 + .../runs/iot_sensors_chiller_1_run_04.json | 21 + .../runs/iot_sensors_chiller_1_run_05.json | 21 + .../runs/iot_sensors_chiller_1_warmup_01.json | 23 + .../timing/runs/utilities_time_run_-1.json | 21 + .../timing/runs/utilities_time_run_-2.json | 21 + .../timing/runs/utilities_time_run_01.json | 21 + .../timing/runs/utilities_time_run_02.json | 21 + .../timing/runs/utilities_time_run_03.json | 21 + .../timing/runs/utilities_time_run_04.json | 21 + .../timing/runs/utilities_time_run_05.json | 21 + src/evaluation/timing_benchmark.py | 380 ++++++++++ src/workflow/executor.py | 21 +- src/workflow/runner.py | 37 +- src/workflow/timing.py | 186 +++++ uv.lock | 686 +++++++++++++++++- 42 files changed, 2077 insertions(+), 20 deletions(-) create mode 100644 artifacts/timing/runs/fmsr_chiller_failure_modes_run_-1.json create mode 100644 artifacts/timing/runs/fmsr_chiller_failure_modes_run_-2.json create mode 100644 artifacts/timing/runs/fmsr_chiller_failure_modes_run_01.json create mode 100644 artifacts/timing/runs/fmsr_chiller_failure_modes_run_02.json create mode 100644 artifacts/timing/runs/fmsr_chiller_failure_modes_run_03.json create mode 100644 artifacts/timing/runs/fmsr_chiller_failure_modes_run_04.json create mode 100644 artifacts/timing/runs/fmsr_chiller_failure_modes_run_05.json create mode 100644 artifacts/timing/runs/iot_assets_main_run_-1.json create mode 100644 artifacts/timing/runs/iot_assets_main_run_-2.json create mode 100644 artifacts/timing/runs/iot_assets_main_run_01.json create mode 100644 artifacts/timing/runs/iot_assets_main_run_02.json create mode 100644 artifacts/timing/runs/iot_assets_main_run_03.json create mode 100644 artifacts/timing/runs/iot_assets_main_run_04.json create mode 100644 artifacts/timing/runs/iot_assets_main_run_05.json create mode 100644 artifacts/timing/runs/iot_assets_main_warmup_01.json create mode 100644 artifacts/timing/runs/iot_observations_ch1_run_-1.json create mode 100644 artifacts/timing/runs/iot_observations_ch1_run_-2.json create mode 100644 artifacts/timing/runs/iot_observations_ch1_run_01.json create mode 100644 artifacts/timing/runs/iot_observations_ch1_run_02.json create mode 100644 artifacts/timing/runs/iot_observations_ch1_run_03.json create mode 100644 artifacts/timing/runs/iot_observations_ch1_run_04.json create mode 100644 artifacts/timing/runs/iot_observations_ch1_run_05.json create mode 100644 artifacts/timing/runs/iot_sensors_chiller_1_run_-1.json create mode 100644 artifacts/timing/runs/iot_sensors_chiller_1_run_-2.json create mode 100644 artifacts/timing/runs/iot_sensors_chiller_1_run_01.json create mode 100644 artifacts/timing/runs/iot_sensors_chiller_1_run_02.json create mode 100644 artifacts/timing/runs/iot_sensors_chiller_1_run_03.json create mode 100644 artifacts/timing/runs/iot_sensors_chiller_1_run_04.json create mode 100644 artifacts/timing/runs/iot_sensors_chiller_1_run_05.json create mode 100644 artifacts/timing/runs/iot_sensors_chiller_1_warmup_01.json create mode 100644 artifacts/timing/runs/utilities_time_run_-1.json create mode 100644 artifacts/timing/runs/utilities_time_run_-2.json create mode 100644 artifacts/timing/runs/utilities_time_run_01.json create mode 100644 artifacts/timing/runs/utilities_time_run_02.json create mode 100644 artifacts/timing/runs/utilities_time_run_03.json create mode 100644 artifacts/timing/runs/utilities_time_run_04.json create mode 100644 artifacts/timing/runs/utilities_time_run_05.json create mode 100644 src/evaluation/timing_benchmark.py create mode 100644 src/workflow/timing.py diff --git a/artifacts/timing/runs/fmsr_chiller_failure_modes_run_-1.json b/artifacts/timing/runs/fmsr_chiller_failure_modes_run_-1.json new file mode 100644 index 000000000..6a638a743 --- /dev/null +++ b/artifacts/timing/runs/fmsr_chiller_failure_modes_run_-1.json @@ -0,0 +1,21 @@ +{ + "run_name": "fmsr_chiller_failure_modes_run_-1", + "group": "fmsr_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 10.858443, + "average_seconds": 10.858443 + } + }, + "total_wall_time_seconds": 10.858827, + "metadata": { + "scenario_name": "fmsr_chiller_failure_modes", + "question_length_chars": 39, + "plan_steps": 2, + "tool_calls": 1, + "server_sequence": "IoTAgent,FMSRAgent", + "unique_servers": "FMSRAgent,IoTAgent" + }, + "created_at_unix": 1775495981.597656 +} \ No newline at end of file diff --git a/artifacts/timing/runs/fmsr_chiller_failure_modes_run_-2.json b/artifacts/timing/runs/fmsr_chiller_failure_modes_run_-2.json new file mode 100644 index 000000000..015cb1a7d --- /dev/null +++ b/artifacts/timing/runs/fmsr_chiller_failure_modes_run_-2.json @@ -0,0 +1,21 @@ +{ + "run_name": "fmsr_chiller_failure_modes_run_-2", + "group": "fmsr_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 17.802149, + "average_seconds": 17.802149 + } + }, + "total_wall_time_seconds": 17.802449, + "metadata": { + "scenario_name": "fmsr_chiller_failure_modes", + "question_length_chars": 39, + "plan_steps": 3, + "tool_calls": 2, + "server_sequence": "FMSRAgent,IoTAgent,FMSRAgent", + "unique_servers": "FMSRAgent,IoTAgent" + }, + "created_at_unix": 1775495999.400982 +} \ No newline at end of file diff --git a/artifacts/timing/runs/fmsr_chiller_failure_modes_run_01.json b/artifacts/timing/runs/fmsr_chiller_failure_modes_run_01.json new file mode 100644 index 000000000..5ab289aa4 --- /dev/null +++ b/artifacts/timing/runs/fmsr_chiller_failure_modes_run_01.json @@ -0,0 +1,21 @@ +{ + "run_name": "fmsr_chiller_failure_modes_run_01", + "group": "fmsr_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 13.492398, + "average_seconds": 13.492398 + } + }, + "total_wall_time_seconds": 13.49285, + "metadata": { + "scenario_name": "fmsr_chiller_failure_modes", + "question_length_chars": 39, + "plan_steps": 2, + "tool_calls": 2, + "server_sequence": "FMSRAgent,FMSRAgent", + "unique_servers": "FMSRAgent" + }, + "created_at_unix": 1775496012.895334 +} \ No newline at end of file diff --git a/artifacts/timing/runs/fmsr_chiller_failure_modes_run_02.json b/artifacts/timing/runs/fmsr_chiller_failure_modes_run_02.json new file mode 100644 index 000000000..cd9787c17 --- /dev/null +++ b/artifacts/timing/runs/fmsr_chiller_failure_modes_run_02.json @@ -0,0 +1,21 @@ +{ + "run_name": "fmsr_chiller_failure_modes_run_02", + "group": "fmsr_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 14.738207, + "average_seconds": 14.738207 + } + }, + "total_wall_time_seconds": 14.738572, + "metadata": { + "scenario_name": "fmsr_chiller_failure_modes", + "question_length_chars": 39, + "plan_steps": 3, + "tool_calls": 2, + "server_sequence": "IoTAgent,IoTAgent,FMSRAgent", + "unique_servers": "FMSRAgent,IoTAgent" + }, + "created_at_unix": 1775496027.6353002 +} \ No newline at end of file diff --git a/artifacts/timing/runs/fmsr_chiller_failure_modes_run_03.json b/artifacts/timing/runs/fmsr_chiller_failure_modes_run_03.json new file mode 100644 index 000000000..f34c7acfb --- /dev/null +++ b/artifacts/timing/runs/fmsr_chiller_failure_modes_run_03.json @@ -0,0 +1,21 @@ +{ + "run_name": "fmsr_chiller_failure_modes_run_03", + "group": "fmsr_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 16.520928, + "average_seconds": 16.520928 + } + }, + "total_wall_time_seconds": 16.521396, + "metadata": { + "scenario_name": "fmsr_chiller_failure_modes", + "question_length_chars": 39, + "plan_steps": 3, + "tool_calls": 2, + "server_sequence": "IoTAgent,IoTAgent,FMSRAgent", + "unique_servers": "FMSRAgent,IoTAgent" + }, + "created_at_unix": 1775496044.157592 +} \ No newline at end of file diff --git a/artifacts/timing/runs/fmsr_chiller_failure_modes_run_04.json b/artifacts/timing/runs/fmsr_chiller_failure_modes_run_04.json new file mode 100644 index 000000000..52b4e4544 --- /dev/null +++ b/artifacts/timing/runs/fmsr_chiller_failure_modes_run_04.json @@ -0,0 +1,21 @@ +{ + "run_name": "fmsr_chiller_failure_modes_run_04", + "group": "fmsr_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 16.560545, + "average_seconds": 16.560545 + } + }, + "total_wall_time_seconds": 16.561162, + "metadata": { + "scenario_name": "fmsr_chiller_failure_modes", + "question_length_chars": 39, + "plan_steps": 3, + "tool_calls": 2, + "server_sequence": "FMSRAgent,IoTAgent,FMSRAgent", + "unique_servers": "FMSRAgent,IoTAgent" + }, + "created_at_unix": 1775496060.7210398 +} \ No newline at end of file diff --git a/artifacts/timing/runs/fmsr_chiller_failure_modes_run_05.json b/artifacts/timing/runs/fmsr_chiller_failure_modes_run_05.json new file mode 100644 index 000000000..28efe57e6 --- /dev/null +++ b/artifacts/timing/runs/fmsr_chiller_failure_modes_run_05.json @@ -0,0 +1,21 @@ +{ + "run_name": "fmsr_chiller_failure_modes_run_05", + "group": "fmsr_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 17.429605, + "average_seconds": 17.429605 + } + }, + "total_wall_time_seconds": 17.430239, + "metadata": { + "scenario_name": "fmsr_chiller_failure_modes", + "question_length_chars": 39, + "plan_steps": 3, + "tool_calls": 2, + "server_sequence": "FMSRAgent,IoTAgent,FMSRAgent", + "unique_servers": "FMSRAgent,IoTAgent" + }, + "created_at_unix": 1775496078.1532428 +} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_assets_main_run_-1.json b/artifacts/timing/runs/iot_assets_main_run_-1.json new file mode 100644 index 000000000..caee9be8f --- /dev/null +++ b/artifacts/timing/runs/iot_assets_main_run_-1.json @@ -0,0 +1,21 @@ +{ + "run_name": "iot_assets_main_run_-1", + "group": "iot_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 8.33804, + "average_seconds": 8.33804 + } + }, + "total_wall_time_seconds": 8.338263, + "metadata": { + "scenario_name": "iot_assets_main", + "question_length_chars": 33, + "plan_steps": 1, + "tool_calls": 1, + "server_sequence": "IoTAgent", + "unique_servers": "IoTAgent" + }, + "created_at_unix": 1775495862.19991 +} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_assets_main_run_-2.json b/artifacts/timing/runs/iot_assets_main_run_-2.json new file mode 100644 index 000000000..8aefe0836 --- /dev/null +++ b/artifacts/timing/runs/iot_assets_main_run_-2.json @@ -0,0 +1,21 @@ +{ + "run_name": "iot_assets_main_run_-2", + "group": "iot_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 5.335888, + "average_seconds": 5.335888 + } + }, + "total_wall_time_seconds": 5.33635, + "metadata": { + "scenario_name": "iot_assets_main", + "question_length_chars": 33, + "plan_steps": 1, + "tool_calls": 1, + "server_sequence": "IoTAgent", + "unique_servers": "IoTAgent" + }, + "created_at_unix": 1775495867.5374138 +} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_assets_main_run_01.json b/artifacts/timing/runs/iot_assets_main_run_01.json new file mode 100644 index 000000000..5b1d69245 --- /dev/null +++ b/artifacts/timing/runs/iot_assets_main_run_01.json @@ -0,0 +1,23 @@ +{ + "run_name": "iot_assets_main_run_01", + "group": "iot_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 4.111411, + "average_seconds": 4.111411 + } + }, + "total_wall_time_seconds": 4.111804, + "metadata": { + "scenario_name": "iot_assets_main", + "success": true, + "failure_reason": "", + "question_length_chars": 33, + "plan_steps": 1, + "tool_calls": 1, + "server_sequence": "IoTAgent", + "unique_servers": "IoTAgent" + }, + "created_at_unix": 1775496687.418485 +} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_assets_main_run_02.json b/artifacts/timing/runs/iot_assets_main_run_02.json new file mode 100644 index 000000000..d539c3200 --- /dev/null +++ b/artifacts/timing/runs/iot_assets_main_run_02.json @@ -0,0 +1,23 @@ +{ + "run_name": "iot_assets_main_run_02", + "group": "iot_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 4.587812, + "average_seconds": 4.587812 + } + }, + "total_wall_time_seconds": 4.588275, + "metadata": { + "scenario_name": "iot_assets_main", + "success": true, + "failure_reason": "", + "question_length_chars": 33, + "plan_steps": 1, + "tool_calls": 1, + "server_sequence": "IoTAgent", + "unique_servers": "IoTAgent" + }, + "created_at_unix": 1775496693.509748 +} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_assets_main_run_03.json b/artifacts/timing/runs/iot_assets_main_run_03.json new file mode 100644 index 000000000..b230df81a --- /dev/null +++ b/artifacts/timing/runs/iot_assets_main_run_03.json @@ -0,0 +1,23 @@ +{ + "run_name": "iot_assets_main_run_03", + "group": "iot_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 4.810847, + "average_seconds": 4.810847 + } + }, + "total_wall_time_seconds": 4.811266, + "metadata": { + "scenario_name": "iot_assets_main", + "success": true, + "failure_reason": "", + "question_length_chars": 33, + "plan_steps": 1, + "tool_calls": 1, + "server_sequence": "IoTAgent", + "unique_servers": "IoTAgent" + }, + "created_at_unix": 1775496699.823505 +} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_assets_main_run_04.json b/artifacts/timing/runs/iot_assets_main_run_04.json new file mode 100644 index 000000000..2569f81be --- /dev/null +++ b/artifacts/timing/runs/iot_assets_main_run_04.json @@ -0,0 +1,21 @@ +{ + "run_name": "iot_assets_main_run_04", + "group": "iot_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 4.839655, + "average_seconds": 4.839655 + } + }, + "total_wall_time_seconds": 4.840056, + "metadata": { + "scenario_name": "iot_assets_main", + "question_length_chars": 33, + "plan_steps": 1, + "tool_calls": 1, + "server_sequence": "IoTAgent", + "unique_servers": "IoTAgent" + }, + "created_at_unix": 1775495887.4010198 +} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_assets_main_run_05.json b/artifacts/timing/runs/iot_assets_main_run_05.json new file mode 100644 index 000000000..47d511210 --- /dev/null +++ b/artifacts/timing/runs/iot_assets_main_run_05.json @@ -0,0 +1,21 @@ +{ + "run_name": "iot_assets_main_run_05", + "group": "iot_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 5.641701, + "average_seconds": 5.641701 + } + }, + "total_wall_time_seconds": 5.64202, + "metadata": { + "scenario_name": "iot_assets_main", + "question_length_chars": 33, + "plan_steps": 1, + "tool_calls": 1, + "server_sequence": "IoTAgent", + "unique_servers": "IoTAgent" + }, + "created_at_unix": 1775495893.044065 +} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_assets_main_warmup_01.json b/artifacts/timing/runs/iot_assets_main_warmup_01.json new file mode 100644 index 000000000..af10a45ea --- /dev/null +++ b/artifacts/timing/runs/iot_assets_main_warmup_01.json @@ -0,0 +1,23 @@ +{ + "run_name": "iot_assets_main_warmup_01", + "group": "iot_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 6.610018, + "average_seconds": 6.610018 + } + }, + "total_wall_time_seconds": 6.610272, + "metadata": { + "scenario_name": "iot_assets_main", + "success": true, + "failure_reason": "", + "question_length_chars": 33, + "plan_steps": 1, + "tool_calls": 1, + "server_sequence": "IoTAgent", + "unique_servers": "IoTAgent" + }, + "created_at_unix": 1775496681.803185 +} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_observations_ch1_run_-1.json b/artifacts/timing/runs/iot_observations_ch1_run_-1.json new file mode 100644 index 000000000..a49581433 --- /dev/null +++ b/artifacts/timing/runs/iot_observations_ch1_run_-1.json @@ -0,0 +1,21 @@ +{ + "run_name": "iot_observations_ch1_run_-1", + "group": "iot_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 39.287675, + "average_seconds": 39.287675 + } + }, + "total_wall_time_seconds": 39.28824, + "metadata": { + "scenario_name": "iot_observations_ch1", + "question_length_chars": 41, + "plan_steps": 6, + "tool_calls": 4, + "server_sequence": "IoTAgent,none,IoTAgent,Utilities,IoTAgent,none", + "unique_servers": "IoTAgent,Utilities,none" + }, + "created_at_unix": 1775496146.766182 +} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_observations_ch1_run_-2.json b/artifacts/timing/runs/iot_observations_ch1_run_-2.json new file mode 100644 index 000000000..7aebfc6bd --- /dev/null +++ b/artifacts/timing/runs/iot_observations_ch1_run_-2.json @@ -0,0 +1,21 @@ +{ + "run_name": "iot_observations_ch1_run_-2", + "group": "iot_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 32.346201, + "average_seconds": 32.346201 + } + }, + "total_wall_time_seconds": 32.34678, + "metadata": { + "scenario_name": "iot_observations_ch1", + "question_length_chars": 41, + "plan_steps": 6, + "tool_calls": 3, + "server_sequence": "Utilities,IoTAgent,none,none,IoTAgent,none", + "unique_servers": "IoTAgent,Utilities,none" + }, + "created_at_unix": 1775496179.116521 +} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_observations_ch1_run_01.json b/artifacts/timing/runs/iot_observations_ch1_run_01.json new file mode 100644 index 000000000..8201f4bdd --- /dev/null +++ b/artifacts/timing/runs/iot_observations_ch1_run_01.json @@ -0,0 +1,21 @@ +{ + "run_name": "iot_observations_ch1_run_01", + "group": "iot_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 23.450538, + "average_seconds": 23.450538 + } + }, + "total_wall_time_seconds": 23.451171, + "metadata": { + "scenario_name": "iot_observations_ch1", + "question_length_chars": 41, + "plan_steps": 6, + "tool_calls": 4, + "server_sequence": "IoTAgent,IoTAgent,IoTAgent,none,IoTAgent,none", + "unique_servers": "IoTAgent,none" + }, + "created_at_unix": 1775496202.569411 +} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_observations_ch1_run_02.json b/artifacts/timing/runs/iot_observations_ch1_run_02.json new file mode 100644 index 000000000..01f051a96 --- /dev/null +++ b/artifacts/timing/runs/iot_observations_ch1_run_02.json @@ -0,0 +1,21 @@ +{ + "run_name": "iot_observations_ch1_run_02", + "group": "iot_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 21.399007, + "average_seconds": 21.399007 + } + }, + "total_wall_time_seconds": 21.39962, + "metadata": { + "scenario_name": "iot_observations_ch1", + "question_length_chars": 41, + "plan_steps": 6, + "tool_calls": 5, + "server_sequence": "IoTAgent,IoTAgent,none,IoTAgent,Utilities,IoTAgent", + "unique_servers": "IoTAgent,Utilities,none" + }, + "created_at_unix": 1775496223.9713979 +} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_observations_ch1_run_03.json b/artifacts/timing/runs/iot_observations_ch1_run_03.json new file mode 100644 index 000000000..7b760b85c --- /dev/null +++ b/artifacts/timing/runs/iot_observations_ch1_run_03.json @@ -0,0 +1,21 @@ +{ + "run_name": "iot_observations_ch1_run_03", + "group": "iot_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 31.433882, + "average_seconds": 31.433882 + } + }, + "total_wall_time_seconds": 31.434382, + "metadata": { + "scenario_name": "iot_observations_ch1", + "question_length_chars": 41, + "plan_steps": 5, + "tool_calls": 4, + "server_sequence": "IoTAgent,Utilities,IoTAgent,none,Utilities", + "unique_servers": "IoTAgent,Utilities,none" + }, + "created_at_unix": 1775496255.408129 +} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_observations_ch1_run_04.json b/artifacts/timing/runs/iot_observations_ch1_run_04.json new file mode 100644 index 000000000..563456d29 --- /dev/null +++ b/artifacts/timing/runs/iot_observations_ch1_run_04.json @@ -0,0 +1,21 @@ +{ + "run_name": "iot_observations_ch1_run_04", + "group": "iot_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 28.356606, + "average_seconds": 28.356606 + } + }, + "total_wall_time_seconds": 28.357171, + "metadata": { + "scenario_name": "iot_observations_ch1", + "question_length_chars": 41, + "plan_steps": 6, + "tool_calls": 3, + "server_sequence": "IoTAgent,none,IoTAgent,none,IoTAgent,none", + "unique_servers": "IoTAgent,none" + }, + "created_at_unix": 1775496283.766704 +} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_observations_ch1_run_05.json b/artifacts/timing/runs/iot_observations_ch1_run_05.json new file mode 100644 index 000000000..28f1c8342 --- /dev/null +++ b/artifacts/timing/runs/iot_observations_ch1_run_05.json @@ -0,0 +1,21 @@ +{ + "run_name": "iot_observations_ch1_run_05", + "group": "iot_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 29.91934, + "average_seconds": 29.91934 + } + }, + "total_wall_time_seconds": 29.919652, + "metadata": { + "scenario_name": "iot_observations_ch1", + "question_length_chars": 41, + "plan_steps": 6, + "tool_calls": 5, + "server_sequence": "IoTAgent,IoTAgent,none,IoTAgent,Utilities,IoTAgent", + "unique_servers": "IoTAgent,Utilities,none" + }, + "created_at_unix": 1775496313.687286 +} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_sensors_chiller_1_run_-1.json b/artifacts/timing/runs/iot_sensors_chiller_1_run_-1.json new file mode 100644 index 000000000..9808e734b --- /dev/null +++ b/artifacts/timing/runs/iot_sensors_chiller_1_run_-1.json @@ -0,0 +1,21 @@ +{ + "run_name": "iot_sensors_chiller_1_run_-1", + "group": "iot_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 12.511002, + "average_seconds": 12.511002 + } + }, + "total_wall_time_seconds": 12.511309, + "metadata": { + "scenario_name": "iot_sensors_chiller_1", + "question_length_chars": 44, + "plan_steps": 3, + "tool_calls": 2, + "server_sequence": "IoTAgent,none,IoTAgent", + "unique_servers": "IoTAgent,none" + }, + "created_at_unix": 1775495905.555922 +} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_sensors_chiller_1_run_-2.json b/artifacts/timing/runs/iot_sensors_chiller_1_run_-2.json new file mode 100644 index 000000000..782d166b1 --- /dev/null +++ b/artifacts/timing/runs/iot_sensors_chiller_1_run_-2.json @@ -0,0 +1,21 @@ +{ + "run_name": "iot_sensors_chiller_1_run_-2", + "group": "iot_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 8.951102, + "average_seconds": 8.951102 + } + }, + "total_wall_time_seconds": 8.951563, + "metadata": { + "scenario_name": "iot_sensors_chiller_1", + "question_length_chars": 44, + "plan_steps": 3, + "tool_calls": 2, + "server_sequence": "IoTAgent,none,IoTAgent", + "unique_servers": "IoTAgent,none" + }, + "created_at_unix": 1775495914.5095239 +} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_sensors_chiller_1_run_01.json b/artifacts/timing/runs/iot_sensors_chiller_1_run_01.json new file mode 100644 index 000000000..06d6e7ef6 --- /dev/null +++ b/artifacts/timing/runs/iot_sensors_chiller_1_run_01.json @@ -0,0 +1,21 @@ +{ + "run_name": "iot_sensors_chiller_1_run_01", + "group": "iot_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 10.607203, + "average_seconds": 10.607203 + } + }, + "total_wall_time_seconds": 10.60754, + "metadata": { + "scenario_name": "iot_sensors_chiller_1", + "question_length_chars": 44, + "plan_steps": 3, + "tool_calls": 2, + "server_sequence": "IoTAgent,none,IoTAgent", + "unique_servers": "IoTAgent,none" + }, + "created_at_unix": 1775495925.117853 +} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_sensors_chiller_1_run_02.json b/artifacts/timing/runs/iot_sensors_chiller_1_run_02.json new file mode 100644 index 000000000..2de307ca2 --- /dev/null +++ b/artifacts/timing/runs/iot_sensors_chiller_1_run_02.json @@ -0,0 +1,21 @@ +{ + "run_name": "iot_sensors_chiller_1_run_02", + "group": "iot_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 12.569179, + "average_seconds": 12.569179 + } + }, + "total_wall_time_seconds": 12.569651, + "metadata": { + "scenario_name": "iot_sensors_chiller_1", + "question_length_chars": 44, + "plan_steps": 3, + "tool_calls": 2, + "server_sequence": "IoTAgent,none,IoTAgent", + "unique_servers": "IoTAgent,none" + }, + "created_at_unix": 1775495937.689574 +} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_sensors_chiller_1_run_03.json b/artifacts/timing/runs/iot_sensors_chiller_1_run_03.json new file mode 100644 index 000000000..80aae9e5a --- /dev/null +++ b/artifacts/timing/runs/iot_sensors_chiller_1_run_03.json @@ -0,0 +1,21 @@ +{ + "run_name": "iot_sensors_chiller_1_run_03", + "group": "iot_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 8.479029, + "average_seconds": 8.479029 + } + }, + "total_wall_time_seconds": 8.479517, + "metadata": { + "scenario_name": "iot_sensors_chiller_1", + "question_length_chars": 44, + "plan_steps": 3, + "tool_calls": 2, + "server_sequence": "IoTAgent,none,IoTAgent", + "unique_servers": "IoTAgent,none" + }, + "created_at_unix": 1775495946.169792 +} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_sensors_chiller_1_run_04.json b/artifacts/timing/runs/iot_sensors_chiller_1_run_04.json new file mode 100644 index 000000000..208b58f70 --- /dev/null +++ b/artifacts/timing/runs/iot_sensors_chiller_1_run_04.json @@ -0,0 +1,21 @@ +{ + "run_name": "iot_sensors_chiller_1_run_04", + "group": "iot_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 10.976555, + "average_seconds": 10.976555 + } + }, + "total_wall_time_seconds": 10.977128, + "metadata": { + "scenario_name": "iot_sensors_chiller_1", + "question_length_chars": 44, + "plan_steps": 3, + "tool_calls": 2, + "server_sequence": "IoTAgent,none,IoTAgent", + "unique_servers": "IoTAgent,none" + }, + "created_at_unix": 1775495957.149072 +} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_sensors_chiller_1_run_05.json b/artifacts/timing/runs/iot_sensors_chiller_1_run_05.json new file mode 100644 index 000000000..0170a1808 --- /dev/null +++ b/artifacts/timing/runs/iot_sensors_chiller_1_run_05.json @@ -0,0 +1,21 @@ +{ + "run_name": "iot_sensors_chiller_1_run_05", + "group": "iot_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 13.517921, + "average_seconds": 13.517921 + } + }, + "total_wall_time_seconds": 13.518375, + "metadata": { + "scenario_name": "iot_sensors_chiller_1", + "question_length_chars": 44, + "plan_steps": 3, + "tool_calls": 2, + "server_sequence": "IoTAgent,none,IoTAgent", + "unique_servers": "IoTAgent,none" + }, + "created_at_unix": 1775495970.7372491 +} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_sensors_chiller_1_warmup_01.json b/artifacts/timing/runs/iot_sensors_chiller_1_warmup_01.json new file mode 100644 index 000000000..f73840f43 --- /dev/null +++ b/artifacts/timing/runs/iot_sensors_chiller_1_warmup_01.json @@ -0,0 +1,23 @@ +{ + "run_name": "iot_sensors_chiller_1_warmup_01", + "group": "iot_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 7.502668, + "average_seconds": 7.502668 + } + }, + "total_wall_time_seconds": 7.503349, + "metadata": { + "scenario_name": "iot_sensors_chiller_1", + "success": false, + "failure_reason": "planner_emitted_agent_none | Unknown agent 'none'. Registered agents: ['IoTAgent', 'Utilities', 'FMSRAgent', 'TSFMAgent']", + "question_length_chars": 44, + "plan_steps": 3, + "tool_calls": 2, + "server_sequence": "IoTAgent,none,IoTAgent", + "unique_servers": "IoTAgent,none" + }, + "created_at_unix": 1775496708.830985 +} \ No newline at end of file diff --git a/artifacts/timing/runs/utilities_time_run_-1.json b/artifacts/timing/runs/utilities_time_run_-1.json new file mode 100644 index 000000000..468c701c0 --- /dev/null +++ b/artifacts/timing/runs/utilities_time_run_-1.json @@ -0,0 +1,21 @@ +{ + "run_name": "utilities_time_run_-1", + "group": "utilities_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 4.707929, + "average_seconds": 4.707929 + } + }, + "total_wall_time_seconds": 4.708558, + "metadata": { + "scenario_name": "utilities_time", + "question_length_chars": 25, + "plan_steps": 1, + "tool_calls": 1, + "server_sequence": "Utilities", + "unique_servers": "Utilities" + }, + "created_at_unix": 1775496082.864054 +} \ No newline at end of file diff --git a/artifacts/timing/runs/utilities_time_run_-2.json b/artifacts/timing/runs/utilities_time_run_-2.json new file mode 100644 index 000000000..6066b80e0 --- /dev/null +++ b/artifacts/timing/runs/utilities_time_run_-2.json @@ -0,0 +1,21 @@ +{ + "run_name": "utilities_time_run_-2", + "group": "utilities_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 3.685504, + "average_seconds": 3.685504 + } + }, + "total_wall_time_seconds": 3.686068, + "metadata": { + "scenario_name": "utilities_time", + "question_length_chars": 25, + "plan_steps": 1, + "tool_calls": 1, + "server_sequence": "Utilities", + "unique_servers": "Utilities" + }, + "created_at_unix": 1775496086.552075 +} \ No newline at end of file diff --git a/artifacts/timing/runs/utilities_time_run_01.json b/artifacts/timing/runs/utilities_time_run_01.json new file mode 100644 index 000000000..83278b608 --- /dev/null +++ b/artifacts/timing/runs/utilities_time_run_01.json @@ -0,0 +1,21 @@ +{ + "run_name": "utilities_time_run_01", + "group": "utilities_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 3.992103, + "average_seconds": 3.992103 + } + }, + "total_wall_time_seconds": 3.992689, + "metadata": { + "scenario_name": "utilities_time", + "question_length_chars": 25, + "plan_steps": 1, + "tool_calls": 1, + "server_sequence": "Utilities", + "unique_servers": "Utilities" + }, + "created_at_unix": 1775496090.547076 +} \ No newline at end of file diff --git a/artifacts/timing/runs/utilities_time_run_02.json b/artifacts/timing/runs/utilities_time_run_02.json new file mode 100644 index 000000000..133967d34 --- /dev/null +++ b/artifacts/timing/runs/utilities_time_run_02.json @@ -0,0 +1,21 @@ +{ + "run_name": "utilities_time_run_02", + "group": "utilities_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 4.351466, + "average_seconds": 4.351466 + } + }, + "total_wall_time_seconds": 4.352046, + "metadata": { + "scenario_name": "utilities_time", + "question_length_chars": 25, + "plan_steps": 1, + "tool_calls": 1, + "server_sequence": "Utilities", + "unique_servers": "Utilities" + }, + "created_at_unix": 1775496094.9015522 +} \ No newline at end of file diff --git a/artifacts/timing/runs/utilities_time_run_03.json b/artifacts/timing/runs/utilities_time_run_03.json new file mode 100644 index 000000000..40090477f --- /dev/null +++ b/artifacts/timing/runs/utilities_time_run_03.json @@ -0,0 +1,21 @@ +{ + "run_name": "utilities_time_run_03", + "group": "utilities_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 3.934517, + "average_seconds": 3.934517 + } + }, + "total_wall_time_seconds": 3.935077, + "metadata": { + "scenario_name": "utilities_time", + "question_length_chars": 25, + "plan_steps": 1, + "tool_calls": 1, + "server_sequence": "Utilities", + "unique_servers": "Utilities" + }, + "created_at_unix": 1775496098.838848 +} \ No newline at end of file diff --git a/artifacts/timing/runs/utilities_time_run_04.json b/artifacts/timing/runs/utilities_time_run_04.json new file mode 100644 index 000000000..92e4583c9 --- /dev/null +++ b/artifacts/timing/runs/utilities_time_run_04.json @@ -0,0 +1,21 @@ +{ + "run_name": "utilities_time_run_04", + "group": "utilities_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 4.815199, + "average_seconds": 4.815199 + } + }, + "total_wall_time_seconds": 4.815743, + "metadata": { + "scenario_name": "utilities_time", + "question_length_chars": 25, + "plan_steps": 1, + "tool_calls": 1, + "server_sequence": "Utilities", + "unique_servers": "Utilities" + }, + "created_at_unix": 1775496103.6566458 +} \ No newline at end of file diff --git a/artifacts/timing/runs/utilities_time_run_05.json b/artifacts/timing/runs/utilities_time_run_05.json new file mode 100644 index 000000000..55fce349a --- /dev/null +++ b/artifacts/timing/runs/utilities_time_run_05.json @@ -0,0 +1,21 @@ +{ + "run_name": "utilities_time_run_05", + "group": "utilities_only", + "phases": { + "question_to_answer": { + "count": 1, + "total_seconds": 3.81609, + "average_seconds": 3.81609 + } + }, + "total_wall_time_seconds": 3.816603, + "metadata": { + "scenario_name": "utilities_time", + "question_length_chars": 25, + "plan_steps": 1, + "tool_calls": 1, + "server_sequence": "Utilities", + "unique_servers": "Utilities" + }, + "created_at_unix": 1775496107.4759 +} \ No newline at end of file diff --git a/src/evaluation/timing_benchmark.py b/src/evaluation/timing_benchmark.py new file mode 100644 index 000000000..55e0228d2 --- /dev/null +++ b/src/evaluation/timing_benchmark.py @@ -0,0 +1,380 @@ +"""Timing benchmark runner for AssetOpsBench orchestration evaluation. + +This script runs repeated timing benchmarks over the single-agent meta-agent +scenario files, logs each run to Weights & Biases via ``workflow.timing``, +and writes aggregate JSON summaries grouped by workload class. +""" + +from __future__ import annotations + +import argparse +import asyncio +import json +import statistics +from collections import defaultdict +from dataclasses import dataclass +from pathlib import Path +from typing import Any + +from dotenv import load_dotenv + +from llm.litellm import LiteLLMBackend +from workflow.runner import PlanExecuteRunner +from workflow.timing import TimingRun + +_SCENARIO_ROOT = Path("src/tmp/meta_agent/scenarios/single_agent") +_IOT_SCENARIO_PATH = _SCENARIO_ROOT / "iot_utterance_meta.json" +_FMSR_SCENARIO_PATH = _SCENARIO_ROOT / "fmsr_utterance.json" + + +@dataclass(frozen=True) +class Scenario: + scenario_id: int + name: str + group: str + question: str + source_file: str + source_type: str + category: str | None = None + deterministic: bool | None = None + + +def _build_parser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser( + description="Run repeated timing benchmarks for AssetOpsBench scenarios." + ) + parser.add_argument( + "--model-id", + default="watsonx/meta-llama/llama-4-maverick-17b-128e-instruct-fp8", + help="LLM model id used by the orchestration runner.", + ) + parser.add_argument( + "--warmup-runs", + type=int, + default=2, + help="Number of warmup runs per scenario to discard.", + ) + parser.add_argument( + "--measured-runs", + type=int, + default=5, + help="Number of measured runs per scenario.", + ) + parser.add_argument( + "--output-dir", + default="artifacts/timing", + help="Directory for per-run and aggregate JSON output.", + ) + parser.add_argument( + "--wandb-project", + required=True, + help="Weights & Biases project name for logging timed runs.", + ) + parser.add_argument( + "--wandb-entity", + default=None, + help="Optional Weights & Biases entity.", + ) + parser.add_argument( + "--wandb-mode", + default=None, + help="Optional Weights & Biases mode, for example 'offline'.", + ) + parser.add_argument( + "--retry-delay-seconds", + type=float, + default=3.0, + help="Delay before retrying a failed or rate-limited scenario run.", + ) + parser.add_argument( + "--inter-run-delay-seconds", + type=float, + default=0.5, + help="Delay between successful runs to reduce provider rate limiting.", + ) + parser.add_argument( + "--max-attempts-multiplier", + type=int, + default=3, + help="Maximum attempts per requested run count multiplier before giving up.", + ) + return parser + + +def _load_scenarios() -> list[Scenario]: + scenarios: list[Scenario] = [] + scenario_specs = [ + (_IOT_SCENARIO_PATH, "iot"), + (_FMSR_SCENARIO_PATH, "fmsr"), + ] + + for path, group in scenario_specs: + records = json.loads(path.read_text()) + for record in records: + scenario_id = int(record["id"]) + scenarios.append( + Scenario( + scenario_id=scenario_id, + name=f"{group}_{scenario_id}", + group=group, + question=record["text"], + source_file=str(path), + source_type=str(record.get("type", group)), + category=record.get("category"), + deterministic=record.get("deterministic"), + ) + ) + + return scenarios + + +def _classify_failure(result, plan) -> list[str]: + failure_reasons: list[str] = [] + + for step in result.history: + if step.success: + continue + error_text = step.error or "unknown_step_error" + failure_reasons.append(error_text) + lowered = error_text.lower() + if ( + "rate limit" in lowered + or "status_code\":429" in lowered + or "status code 429" in lowered + or "rate_limit_reached_requests" in lowered + or "consumption_limit_reached" in lowered + ): + failure_reasons.append("rate_limited") + if "token_quota_reached" in lowered or "quota" in lowered: + failure_reasons.append("quota_exhausted") + + return list(dict.fromkeys(failure_reasons)) + + +async def _run_scenario_once( + *, + scenario: Scenario, + model_id: str, + output_dir: Path, + wandb_project: str, + wandb_entity: str | None, + wandb_mode: str | None, + run_index: int, +) -> tuple[dict[str, Any], bool, str | None]: + llm = LiteLLMBackend(model_id=model_id) + runner = PlanExecuteRunner(llm=llm) + + run_label = ( + f"warmup_{abs(run_index):02d}" if run_index < 0 else f"run_{run_index:02d}" + ) + run_name = f"{scenario.name}_{run_label}" + timer = TimingRun( + project=wandb_project, + entity=wandb_entity, + mode=wandb_mode, + run_name=run_name, + group=scenario.group, + config={ + "scenario_id": scenario.scenario_id, + "scenario_name": scenario.name, + "question": scenario.question, + "model_id": model_id, + "workload_group": scenario.group, + "source_file": scenario.source_file, + "source_type": scenario.source_type, + "category": scenario.category, + "deterministic": scenario.deterministic, + }, + tags=[scenario.group, "timing-benchmark"], + ) + + with timer.phase("question_to_answer"): + result = await runner.run(scenario.question, timer=timer) + + failure_reasons = _classify_failure(result, result.plan) + success = len(failure_reasons) == 0 + failure_reason = " | ".join(failure_reasons) if failure_reasons else None + server_sequence = [step.agent for step in result.history] + + summary = timer.finish( + extra_metrics={ + "scenario_id": scenario.scenario_id, + "scenario_name": scenario.name, + "scenario_text": scenario.question, + "source_file": scenario.source_file, + "source_type": scenario.source_type, + "category": scenario.category or "", + "deterministic": ( + "" if scenario.deterministic is None else scenario.deterministic + ), + "success": success, + "failure_reason": failure_reason or "", + "question_length_chars": len(scenario.question), + "plan_steps": len(result.plan.steps), + "tool_calls": sum( + 1 + for step in result.history + if step.tool and step.tool.lower() not in ("none", "null", "") + ), + "server_sequence": ",".join(server_sequence), + "unique_servers": ",".join(sorted(set(server_sequence))), + }, + summary_path=str(output_dir / "runs" / f"{run_name}.json"), + ) + + return summary.to_dict(), success, failure_reason + + +def _describe(values: list[float]) -> dict[str, float | int]: + if not values: + return {"count": 0, "mean": 0.0, "std": 0.0, "min": 0.0, "max": 0.0} + std = statistics.stdev(values) if len(values) > 1 else 0.0 + return { + "count": len(values), + "mean": round(statistics.mean(values), 6), + "std": round(std, 6), + "min": round(min(values), 6), + "max": round(max(values), 6), + } + + +def _aggregate_runs(run_summaries: list[dict[str, Any]]) -> dict[str, Any]: + grouped: dict[str, list[dict[str, Any]]] = defaultdict(list) + for summary in run_summaries: + grouped[summary["group"]].append(summary) + + aggregate: dict[str, Any] = {"groups": {}, "overall": {}} + + all_total_times = [s["total_wall_time_seconds"] for s in run_summaries] + aggregate["overall"]["total_wall_time_seconds"] = _describe(all_total_times) + all_phase_names = sorted( + {phase for summary in run_summaries for phase in summary["phases"].keys()} + ) + aggregate["overall"]["phases"] = {} + for phase_name in all_phase_names: + phase_values = [ + float(summary["phases"][phase_name]["total_seconds"]) + for summary in run_summaries + if phase_name in summary["phases"] + ] + aggregate["overall"]["phases"][phase_name] = _describe(phase_values) + + for group, summaries in sorted(grouped.items()): + phase_names = sorted( + {phase for summary in summaries for phase in summary["phases"].keys()} + ) + group_total_times = [s["total_wall_time_seconds"] for s in summaries] + group_result: dict[str, Any] = { + "num_runs": len(summaries), + "total_wall_time_seconds": _describe(group_total_times), + "phases": {}, + "scenarios": sorted({s["metadata"]["scenario_name"] for s in summaries}), + "scenario_ids": sorted({int(s["metadata"]["scenario_id"]) for s in summaries}), + } + for phase_name in phase_names: + phase_values = [ + float(summary["phases"][phase_name]["total_seconds"]) + for summary in summaries + if phase_name in summary["phases"] + ] + group_result["phases"][phase_name] = _describe(phase_values) + aggregate["groups"][group] = group_result + + return aggregate + + +async def _main(args: argparse.Namespace) -> None: + output_dir = Path(args.output_dir) + output_dir.mkdir(parents=True, exist_ok=True) + + measured_runs: list[dict[str, Any]] = [] + dropped_runs: list[dict[str, Any]] = [] + scenarios = _load_scenarios() + + for scenario in scenarios: + print(f"Scenario: {scenario.name} [{scenario.group}]") + max_warmup_attempts = max(1, args.warmup_runs * args.max_attempts_multiplier) + warmups_completed = 0 + warmup_attempt = 0 + + while ( + warmups_completed < args.warmup_runs + and warmup_attempt < max_warmup_attempts + ): + warmup_attempt += 1 + print( + f" Warmup {warmups_completed + 1}/{args.warmup_runs} " + f"(attempt {warmup_attempt})" + ) + summary, success, failure_reason = await _run_scenario_once( + scenario=scenario, + model_id=args.model_id, + output_dir=output_dir, + wandb_project=args.wandb_project, + wandb_entity=args.wandb_entity, + wandb_mode=args.wandb_mode, + run_index=-(warmups_completed + 1), + ) + if success: + warmups_completed += 1 + await asyncio.sleep(args.inter_run_delay_seconds) + else: + dropped_runs.append(summary) + print(f" Dropped warmup run: {failure_reason}") + await asyncio.sleep(args.retry_delay_seconds) + + if warmups_completed < args.warmup_runs: + print(" Unable to complete requested warmup runs; moving on.") + + max_measured_attempts = max( + 1, args.measured_runs * args.max_attempts_multiplier + ) + measured_completed = 0 + measured_attempt = 0 + + while ( + measured_completed < args.measured_runs + and measured_attempt < max_measured_attempts + ): + measured_attempt += 1 + print( + f" Measured {measured_completed + 1}/{args.measured_runs} " + f"(attempt {measured_attempt})" + ) + summary, success, failure_reason = await _run_scenario_once( + scenario=scenario, + model_id=args.model_id, + output_dir=output_dir, + wandb_project=args.wandb_project, + wandb_entity=args.wandb_entity, + wandb_mode=args.wandb_mode, + run_index=measured_completed + 1, + ) + if success: + measured_runs.append(summary) + measured_completed += 1 + await asyncio.sleep(args.inter_run_delay_seconds) + else: + dropped_runs.append(summary) + print(f" Dropped measured run: {failure_reason}") + await asyncio.sleep(args.retry_delay_seconds) + + if measured_completed < args.measured_runs: + print(" Unable to complete requested measured runs for this scenario.") + + aggregate = _aggregate_runs(measured_runs) + (output_dir / "aggregate.json").write_text(json.dumps(aggregate, indent=2)) + (output_dir / "dropped_runs.json").write_text(json.dumps(dropped_runs, indent=2)) + + print(f"\nSaved aggregate timing summary to {output_dir / 'aggregate.json'}") + print(f"Saved dropped run details to {output_dir / 'dropped_runs.json'}") + + +def main() -> None: + load_dotenv() + args = _build_parser().parse_args() + asyncio.run(_main(args)) + + +if __name__ == "__main__": + main() diff --git a/src/workflow/executor.py b/src/workflow/executor.py index e84703d00..efdceb8ca 100644 --- a/src/workflow/executor.py +++ b/src/workflow/executor.py @@ -120,6 +120,17 @@ async def execute_step( them from prior step results. 4. Call the tool and return its result. """ + + if not step.tool or step.tool.lower() in ("none", "null"): + return StepResult( + step_number=step.step_number, + task=step.task, + agent=step.agent, + response=step.expected_output, + tool=step.tool, + tool_args=step.tool_args, + ) + server_path = self._server_paths.get(step.agent) if server_path is None: return StepResult( @@ -133,15 +144,7 @@ async def execute_step( ), ) - if not step.tool or step.tool.lower() in ("none", "null"): - return StepResult( - step_number=step.step_number, - task=step.task, - agent=step.agent, - response=step.expected_output, - tool=step.tool, - tool_args=step.tool_args, - ) + try: if _has_placeholders(step.tool_args): diff --git a/src/workflow/runner.py b/src/workflow/runner.py index 87ca789bf..d7adfa291 100644 --- a/src/workflow/runner.py +++ b/src/workflow/runner.py @@ -22,6 +22,7 @@ from .executor import Executor from .models import OrchestratorResult from .planner import Planner +from .timing import TimingRun _SUMMARIZE_PROMPT = """\ You are summarizing the results of a multi-step task execution for an \ @@ -66,7 +67,11 @@ def __init__( self._planner = Planner(llm) self._executor = Executor(llm, server_paths) - async def run(self, question: str) -> OrchestratorResult: + async def run( + self, + question: str, + timer: TimingRun | None = None, + ) -> OrchestratorResult: """Run the full plan-execute loop for a question. Steps: @@ -84,15 +89,27 @@ async def run(self, question: str) -> OrchestratorResult: """ # 1. Discover _log.info("Discovering agent capabilities...") - agent_descriptions = await self._executor.get_agent_descriptions() + if timer is None: + agent_descriptions = await self._executor.get_agent_descriptions() + else: + with timer.phase("discover"): + agent_descriptions = await self._executor.get_agent_descriptions() # 2. Plan _log.info("Planning...") - plan = self._planner.generate_plan(question, agent_descriptions) + if timer is None: + plan = self._planner.generate_plan(question, agent_descriptions) + else: + with timer.phase("plan"): + plan = self._planner.generate_plan(question, agent_descriptions) _log.info("Plan has %d step(s).", len(plan.steps)) # 3. Execute - history = await self._executor.execute_plan(plan, question) + if timer is None: + history = await self._executor.execute_plan(plan, question) + else: + with timer.phase("execute"): + history = await self._executor.execute_plan(plan, question) # 4. Summarise _log.info("Summarising...") @@ -101,9 +118,15 @@ async def run(self, question: str) -> OrchestratorResult: + (r.response if r.success else f"ERROR: {r.error}") for r in history ) - answer = self._llm.generate( - _SUMMARIZE_PROMPT.format(question=question, results=results_text) - ) + if timer is None: + answer = self._llm.generate( + _SUMMARIZE_PROMPT.format(question=question, results=results_text) + ) + else: + with timer.phase("summarise"): + answer = self._llm.generate( + _SUMMARIZE_PROMPT.format(question=question, results=results_text) + ) return OrchestratorResult( question=question, diff --git a/src/workflow/timing.py b/src/workflow/timing.py new file mode 100644 index 000000000..edca59254 --- /dev/null +++ b/src/workflow/timing.py @@ -0,0 +1,186 @@ +""" +Example: + from workflow.timing import TimingRun + + timer = TimingRun( + project="assetopsbench", + run_name="plan_execute_scenario_01", + group="iot_only", + config={"orchestrator": "plan_execute"}, + ) + + with timer.phase("total"): + with timer.phase("planning"): + ... + with timer.phase("execution"): + ... + with timer.phase("summarization"): + ... + + summary = timer.finish( + extra_metrics={"tool_calls": 2, "plan_steps": 3}, + summary_path="artifacts/timing/run_01.json", + ) +""" + +from __future__ import annotations + +import json +import time +from contextlib import contextmanager +from dataclasses import dataclass, field +from pathlib import Path +from typing import Any + + +def _load_wandb(): + try: + import wandb + + return wandb + except ImportError: + return None + + +@dataclass +class TimingPhase: + """Aggregated timings for one named phase.""" + + count: int = 0 + total_seconds: float = 0.0 + + def add(self, elapsed_seconds: float) -> None: + self.count += 1 + self.total_seconds += elapsed_seconds + + @property + def average_seconds(self) -> float: + return self.total_seconds / self.count if self.count else 0.0 + + +@dataclass +class TimingSummary: + """Serializable summary of a timing run.""" + + run_name: str + group: str + phases: dict[str, dict[str, float | int]] + total_wall_time_seconds: float + metadata: dict[str, Any] = field(default_factory=dict) + created_at_unix: float = field(default_factory=time.time) + + def to_dict(self) -> dict[str, Any]: + return { + "run_name": self.run_name, + "group": self.group, + "phases": self.phases, + "total_wall_time_seconds": self.total_wall_time_seconds, + "metadata": self.metadata, + "created_at_unix": self.created_at_unix, + } + + +class TimingRun: + """Context-managed timer for end-to-end runs and named sub-phases.""" + + def __init__( + self, + *, + project: str | None = None, + run_name: str, + group: str, + entity: str | None = None, + mode: str | None = None, + config: dict[str, Any] | None = None, + tags: list[str] | None = None, + ) -> None: + self.project = project + self.run_name = run_name + self.group = group + self.entity = entity + self.mode = mode + self.config = config or {} + self.tags = tags or [] + + self._started_at = time.perf_counter() + self._phases: dict[str, TimingPhase] = {} + self._wandb = None + self._wandb_run = None + + if self.project: + wandb = _load_wandb() + if wandb is not None: + self._wandb = wandb + self._wandb_run = wandb.init( + project=self.project, + entity=self.entity, + mode=self.mode, + name=self.run_name, + group=self.group, + config=self.config, + tags=self.tags, + reinit=True, + ) + + @contextmanager + def phase(self, name: str): + """Measure a named phase.""" + start = time.perf_counter() + try: + yield + finally: + elapsed = time.perf_counter() - start + self._phases.setdefault(name, TimingPhase()).add(elapsed) + + def mark(self, name: str, elapsed_seconds: float) -> None: + """Record a timing value that was measured elsewhere.""" + self._phases.setdefault(name, TimingPhase()).add(elapsed_seconds) + + def finish( + self, + *, + extra_metrics: dict[str, Any] | None = None, + summary_path: str | None = None, + ) -> TimingSummary: + total_wall = time.perf_counter() - self._started_at + phases = { + name: { + "count": phase.count, + "total_seconds": round(phase.total_seconds, 6), + "average_seconds": round(phase.average_seconds, 6), + } + for name, phase in sorted(self._phases.items()) + } + metadata = dict(extra_metrics or {}) + summary = TimingSummary( + run_name=self.run_name, + group=self.group, + phases=phases, + total_wall_time_seconds=round(total_wall, 6), + metadata=metadata, + ) + + if summary_path: + path = Path(summary_path) + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(json.dumps(summary.to_dict(), indent=2)) + + if self._wandb_run is not None: + payload: dict[str, Any] = { + "timing/total_wall_time_seconds": summary.total_wall_time_seconds, + } + for phase_name, values in phases.items(): + payload[f"timing/{phase_name}/total_seconds"] = values["total_seconds"] + payload[f"timing/{phase_name}/average_seconds"] = values[ + "average_seconds" + ] + payload[f"timing/{phase_name}/count"] = values["count"] + for key, value in metadata.items(): + if isinstance(value, (int, float, str, bool)): + payload[f"meta/{key}"] = value + self._wandb_run.log(payload) + self._wandb_run.summary.update(summary.to_dict()) + self._wandb_run.finish() + self._wandb_run = None + + return summary diff --git a/uv.lock b/uv.lock index 5fb8747b0..0af782e0b 100644 --- a/uv.lock +++ b/uv.lock @@ -1,10 +1,13 @@ version = 1 revision = 3 -requires-python = ">=3.14" +requires-python = ">=3.12" resolution-markers = [ - "sys_platform == 'win32'", - "sys_platform == 'emscripten'", - "sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version >= '3.14' and sys_platform == 'win32'", + "python_full_version >= '3.14' and sys_platform == 'emscripten'", + "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version < '3.14' and sys_platform == 'win32'", + "python_full_version < '3.14' and sys_platform == 'emscripten'", + "python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", ] [[package]] @@ -31,6 +34,40 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/50/42/32cf8e7704ceb4481406eb87161349abb46a57fee3f008ba9cb610968646/aiohttp-3.13.3.tar.gz", hash = "sha256:a949eee43d3782f2daae4f4a2819b2cb9b0c5d3b7f7a927067cc84dafdbb9f88", size = 7844556, upload-time = "2026-01-03T17:33:05.204Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/be/4fc11f202955a69e0db803a12a062b8379c970c7c84f4882b6da17337cc1/aiohttp-3.13.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b903a4dfee7d347e2d87697d0713be59e0b87925be030c9178c5faa58ea58d5c", size = 739732, upload-time = "2026-01-03T17:30:14.23Z" }, + { url = "https://files.pythonhosted.org/packages/97/2c/621d5b851f94fa0bb7430d6089b3aa970a9d9b75196bc93bb624b0db237a/aiohttp-3.13.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a45530014d7a1e09f4a55f4f43097ba0fd155089372e105e4bff4ca76cb1b168", size = 494293, upload-time = "2026-01-03T17:30:15.96Z" }, + { url = "https://files.pythonhosted.org/packages/5d/43/4be01406b78e1be8320bb8316dc9c42dbab553d281c40364e0f862d5661c/aiohttp-3.13.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:27234ef6d85c914f9efeb77ff616dbf4ad2380be0cda40b4db086ffc7ddd1b7d", size = 493533, upload-time = "2026-01-03T17:30:17.431Z" }, + { url = "https://files.pythonhosted.org/packages/8d/a8/5a35dc56a06a2c90d4742cbf35294396907027f80eea696637945a106f25/aiohttp-3.13.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d32764c6c9aafb7fb55366a224756387cd50bfa720f32b88e0e6fa45b27dcf29", size = 1737839, upload-time = "2026-01-03T17:30:19.422Z" }, + { url = "https://files.pythonhosted.org/packages/bf/62/4b9eeb331da56530bf2e198a297e5303e1c1ebdceeb00fe9b568a65c5a0c/aiohttp-3.13.3-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b1a6102b4d3ebc07dad44fbf07b45bb600300f15b552ddf1851b5390202ea2e3", size = 1703932, upload-time = "2026-01-03T17:30:21.756Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f6/af16887b5d419e6a367095994c0b1332d154f647e7dc2bd50e61876e8e3d/aiohttp-3.13.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c014c7ea7fb775dd015b2d3137378b7be0249a448a1612268b5a90c2d81de04d", size = 1771906, upload-time = "2026-01-03T17:30:23.932Z" }, + { url = "https://files.pythonhosted.org/packages/ce/83/397c634b1bcc24292fa1e0c7822800f9f6569e32934bdeef09dae7992dfb/aiohttp-3.13.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2b8d8ddba8f95ba17582226f80e2de99c7a7948e66490ef8d947e272a93e9463", size = 1871020, upload-time = "2026-01-03T17:30:26Z" }, + { url = "https://files.pythonhosted.org/packages/86/f6/a62cbbf13f0ac80a70f71b1672feba90fdb21fd7abd8dbf25c0105fb6fa3/aiohttp-3.13.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9ae8dd55c8e6c4257eae3a20fd2c8f41edaea5992ed67156642493b8daf3cecc", size = 1755181, upload-time = "2026-01-03T17:30:27.554Z" }, + { url = "https://files.pythonhosted.org/packages/0a/87/20a35ad487efdd3fba93d5843efdfaa62d2f1479eaafa7453398a44faf13/aiohttp-3.13.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:01ad2529d4b5035578f5081606a465f3b814c542882804e2e8cda61adf5c71bf", size = 1561794, upload-time = "2026-01-03T17:30:29.254Z" }, + { url = "https://files.pythonhosted.org/packages/de/95/8fd69a66682012f6716e1bc09ef8a1a2a91922c5725cb904689f112309c4/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bb4f7475e359992b580559e008c598091c45b5088f28614e855e42d39c2f1033", size = 1697900, upload-time = "2026-01-03T17:30:31.033Z" }, + { url = "https://files.pythonhosted.org/packages/e5/66/7b94b3b5ba70e955ff597672dad1691333080e37f50280178967aff68657/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:c19b90316ad3b24c69cd78d5c9b4f3aa4497643685901185b65166293d36a00f", size = 1728239, upload-time = "2026-01-03T17:30:32.703Z" }, + { url = "https://files.pythonhosted.org/packages/47/71/6f72f77f9f7d74719692ab65a2a0252584bf8d5f301e2ecb4c0da734530a/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:96d604498a7c782cb15a51c406acaea70d8c027ee6b90c569baa6e7b93073679", size = 1740527, upload-time = "2026-01-03T17:30:34.695Z" }, + { url = "https://files.pythonhosted.org/packages/fa/b4/75ec16cbbd5c01bdaf4a05b19e103e78d7ce1ef7c80867eb0ace42ff4488/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:084911a532763e9d3dd95adf78a78f4096cd5f58cdc18e6fdbc1b58417a45423", size = 1554489, upload-time = "2026-01-03T17:30:36.864Z" }, + { url = "https://files.pythonhosted.org/packages/52/8f/bc518c0eea29f8406dcf7ed1f96c9b48e3bc3995a96159b3fc11f9e08321/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:7a4a94eb787e606d0a09404b9c38c113d3b099d508021faa615d70a0131907ce", size = 1767852, upload-time = "2026-01-03T17:30:39.433Z" }, + { url = "https://files.pythonhosted.org/packages/9d/f2/a07a75173124f31f11ea6f863dc44e6f09afe2bca45dd4e64979490deab1/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:87797e645d9d8e222e04160ee32aa06bc5c163e8499f24db719e7852ec23093a", size = 1722379, upload-time = "2026-01-03T17:30:41.081Z" }, + { url = "https://files.pythonhosted.org/packages/3c/4a/1a3fee7c21350cac78e5c5cef711bac1b94feca07399f3d406972e2d8fcd/aiohttp-3.13.3-cp312-cp312-win32.whl", hash = "sha256:b04be762396457bef43f3597c991e192ee7da460a4953d7e647ee4b1c28e7046", size = 428253, upload-time = "2026-01-03T17:30:42.644Z" }, + { url = "https://files.pythonhosted.org/packages/d9/b7/76175c7cb4eb73d91ad63c34e29fc4f77c9386bba4a65b53ba8e05ee3c39/aiohttp-3.13.3-cp312-cp312-win_amd64.whl", hash = "sha256:e3531d63d3bdfa7e3ac5e9b27b2dd7ec9df3206a98e0b3445fa906f233264c57", size = 455407, upload-time = "2026-01-03T17:30:44.195Z" }, + { url = "https://files.pythonhosted.org/packages/97/8a/12ca489246ca1faaf5432844adbfce7ff2cc4997733e0af120869345643a/aiohttp-3.13.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:5dff64413671b0d3e7d5918ea490bdccb97a4ad29b3f311ed423200b2203e01c", size = 734190, upload-time = "2026-01-03T17:30:45.832Z" }, + { url = "https://files.pythonhosted.org/packages/32/08/de43984c74ed1fca5c014808963cc83cb00d7bb06af228f132d33862ca76/aiohttp-3.13.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:87b9aab6d6ed88235aa2970294f496ff1a1f9adcd724d800e9b952395a80ffd9", size = 491783, upload-time = "2026-01-03T17:30:47.466Z" }, + { url = "https://files.pythonhosted.org/packages/17/f8/8dd2cf6112a5a76f81f81a5130c57ca829d101ad583ce57f889179accdda/aiohttp-3.13.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:425c126c0dc43861e22cb1c14ba4c8e45d09516d0a3ae0a3f7494b79f5f233a3", size = 490704, upload-time = "2026-01-03T17:30:49.373Z" }, + { url = "https://files.pythonhosted.org/packages/6d/40/a46b03ca03936f832bc7eaa47cfbb1ad012ba1be4790122ee4f4f8cba074/aiohttp-3.13.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7f9120f7093c2a32d9647abcaf21e6ad275b4fbec5b55969f978b1a97c7c86bf", size = 1720652, upload-time = "2026-01-03T17:30:50.974Z" }, + { url = "https://files.pythonhosted.org/packages/f7/7e/917fe18e3607af92657e4285498f500dca797ff8c918bd7d90b05abf6c2a/aiohttp-3.13.3-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:697753042d57f4bf7122cab985bf15d0cef23c770864580f5af4f52023a56bd6", size = 1692014, upload-time = "2026-01-03T17:30:52.729Z" }, + { url = "https://files.pythonhosted.org/packages/71/b6/cefa4cbc00d315d68973b671cf105b21a609c12b82d52e5d0c9ae61d2a09/aiohttp-3.13.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6de499a1a44e7de70735d0b39f67c8f25eb3d91eb3103be99ca0fa882cdd987d", size = 1759777, upload-time = "2026-01-03T17:30:54.537Z" }, + { url = "https://files.pythonhosted.org/packages/fb/e3/e06ee07b45e59e6d81498b591fc589629be1553abb2a82ce33efe2a7b068/aiohttp-3.13.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:37239e9f9a7ea9ac5bf6b92b0260b01f8a22281996da609206a84df860bc1261", size = 1861276, upload-time = "2026-01-03T17:30:56.512Z" }, + { url = "https://files.pythonhosted.org/packages/7c/24/75d274228acf35ceeb2850b8ce04de9dd7355ff7a0b49d607ee60c29c518/aiohttp-3.13.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f76c1e3fe7d7c8afad7ed193f89a292e1999608170dcc9751a7462a87dfd5bc0", size = 1743131, upload-time = "2026-01-03T17:30:58.256Z" }, + { url = "https://files.pythonhosted.org/packages/04/98/3d21dde21889b17ca2eea54fdcff21b27b93f45b7bb94ca029c31ab59dc3/aiohttp-3.13.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fc290605db2a917f6e81b0e1e0796469871f5af381ce15c604a3c5c7e51cb730", size = 1556863, upload-time = "2026-01-03T17:31:00.445Z" }, + { url = "https://files.pythonhosted.org/packages/9e/84/da0c3ab1192eaf64782b03971ab4055b475d0db07b17eff925e8c93b3aa5/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4021b51936308aeea0367b8f006dc999ca02bc118a0cc78c303f50a2ff6afb91", size = 1682793, upload-time = "2026-01-03T17:31:03.024Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0f/5802ada182f575afa02cbd0ec5180d7e13a402afb7c2c03a9aa5e5d49060/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:49a03727c1bba9a97d3e93c9f93ca03a57300f484b6e935463099841261195d3", size = 1716676, upload-time = "2026-01-03T17:31:04.842Z" }, + { url = "https://files.pythonhosted.org/packages/3f/8c/714d53bd8b5a4560667f7bbbb06b20c2382f9c7847d198370ec6526af39c/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3d9908a48eb7416dc1f4524e69f1d32e5d90e3981e4e37eb0aa1cd18f9cfa2a4", size = 1733217, upload-time = "2026-01-03T17:31:06.868Z" }, + { url = "https://files.pythonhosted.org/packages/7d/79/e2176f46d2e963facea939f5be2d26368ce543622be6f00a12844d3c991f/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:2712039939ec963c237286113c68dbad80a82a4281543f3abf766d9d73228998", size = 1552303, upload-time = "2026-01-03T17:31:08.958Z" }, + { url = "https://files.pythonhosted.org/packages/ab/6a/28ed4dea1759916090587d1fe57087b03e6c784a642b85ef48217b0277ae/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:7bfdc049127717581866fa4708791220970ce291c23e28ccf3922c700740fdc0", size = 1763673, upload-time = "2026-01-03T17:31:10.676Z" }, + { url = "https://files.pythonhosted.org/packages/e8/35/4a3daeb8b9fab49240d21c04d50732313295e4bd813a465d840236dd0ce1/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8057c98e0c8472d8846b9c79f56766bcc57e3e8ac7bfd510482332366c56c591", size = 1721120, upload-time = "2026-01-03T17:31:12.575Z" }, + { url = "https://files.pythonhosted.org/packages/bc/9f/d643bb3c5fb99547323e635e251c609fbbc660d983144cfebec529e09264/aiohttp-3.13.3-cp313-cp313-win32.whl", hash = "sha256:1449ceddcdbcf2e0446957863af03ebaaa03f94c090f945411b61269e2cb5daf", size = 427383, upload-time = "2026-01-03T17:31:14.382Z" }, + { url = "https://files.pythonhosted.org/packages/4e/f1/ab0395f8a79933577cdd996dd2f9aa6014af9535f65dddcf88204682fe62/aiohttp-3.13.3-cp313-cp313-win_amd64.whl", hash = "sha256:693781c45a4033d31d4187d2436f5ac701e7bbfe5df40d917736108c1cc7436e", size = 453899, upload-time = "2026-01-03T17:31:15.958Z" }, { url = "https://files.pythonhosted.org/packages/99/36/5b6514a9f5d66f4e2597e40dea2e3db271e023eb7a5d22defe96ba560996/aiohttp-3.13.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:ea37047c6b367fd4bd632bff8077449b8fa034b69e812a18e0132a00fae6e808", size = 737238, upload-time = "2026-01-03T17:31:17.909Z" }, { url = "https://files.pythonhosted.org/packages/f7/49/459327f0d5bcd8c6c9ca69e60fdeebc3622861e696490d8674a6d0cb90a6/aiohttp-3.13.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:6fc0e2337d1a4c3e6acafda6a78a39d4c14caea625124817420abceed36e2415", size = 492292, upload-time = "2026-01-03T17:31:19.919Z" }, { url = "https://files.pythonhosted.org/packages/e8/0b/b97660c5fd05d3495b4eb27f2d0ef18dc1dc4eff7511a9bf371397ff0264/aiohttp-3.13.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c685f2d80bb67ca8c3837823ad76196b3694b0159d232206d1e461d3d434666f", size = 493021, upload-time = "2026-01-03T17:31:21.636Z" }, @@ -73,6 +110,7 @@ version = "1.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "frozenlist" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" } wheels = [ @@ -103,6 +141,7 @@ version = "4.12.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "idna" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/96/f0/5eb65b2bb0d09ac6776f2eb54adee6abe8228ea05b20a5ad0e4945de8aac/anyio-4.12.1.tar.gz", hash = "sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703", size = 228685, upload-time = "2026-01-06T11:45:21.246Z" } wheels = [ @@ -215,6 +254,30 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d", size = 185271, upload-time = "2025-09-08T23:22:44.795Z" }, + { url = "https://files.pythonhosted.org/packages/df/a2/781b623f57358e360d62cdd7a8c681f074a71d445418a776eef0aadb4ab4/cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c", size = 181048, upload-time = "2025-09-08T23:22:45.938Z" }, + { url = "https://files.pythonhosted.org/packages/ff/df/a4f0fbd47331ceeba3d37c2e51e9dfc9722498becbeec2bd8bc856c9538a/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", size = 212529, upload-time = "2025-09-08T23:22:47.349Z" }, + { url = "https://files.pythonhosted.org/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", size = 220097, upload-time = "2025-09-08T23:22:48.677Z" }, + { url = "https://files.pythonhosted.org/packages/c2/95/7a135d52a50dfa7c882ab0ac17e8dc11cec9d55d2c18dda414c051c5e69e/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e", size = 207983, upload-time = "2025-09-08T23:22:50.06Z" }, + { url = "https://files.pythonhosted.org/packages/3a/c8/15cb9ada8895957ea171c62dc78ff3e99159ee7adb13c0123c001a2546c1/cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037", size = 206519, upload-time = "2025-09-08T23:22:51.364Z" }, + { url = "https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", size = 219572, upload-time = "2025-09-08T23:22:52.902Z" }, + { url = "https://files.pythonhosted.org/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", size = 222963, upload-time = "2025-09-08T23:22:54.518Z" }, + { url = "https://files.pythonhosted.org/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", size = 221361, upload-time = "2025-09-08T23:22:55.867Z" }, + { url = "https://files.pythonhosted.org/packages/7b/2b/2b6435f76bfeb6bbf055596976da087377ede68df465419d192acf00c437/cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18", size = 172932, upload-time = "2025-09-08T23:22:57.188Z" }, + { url = "https://files.pythonhosted.org/packages/f8/ed/13bd4418627013bec4ed6e54283b1959cf6db888048c7cf4b4c3b5b36002/cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5", size = 183557, upload-time = "2025-09-08T23:22:58.351Z" }, + { url = "https://files.pythonhosted.org/packages/95/31/9f7f93ad2f8eff1dbc1c3656d7ca5bfd8fb52c9d786b4dcf19b2d02217fa/cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6", size = 177762, upload-time = "2025-09-08T23:22:59.668Z" }, + { url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" }, + { url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" }, + { url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" }, + { url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" }, + { url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" }, + { url = "https://files.pythonhosted.org/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", size = 206422, upload-time = "2025-09-08T23:23:07.753Z" }, + { url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" }, + { url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" }, + { url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" }, + { url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909, upload-time = "2025-09-08T23:23:14.32Z" }, + { url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402, upload-time = "2025-09-08T23:23:15.535Z" }, + { url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780, upload-time = "2025-09-08T23:23:16.761Z" }, { url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", size = 185320, upload-time = "2025-09-08T23:23:18.087Z" }, { url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", size = 181487, upload-time = "2025-09-08T23:23:19.622Z" }, { url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" }, @@ -245,6 +308,38 @@ version = "3.4.4" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/f3/85/1637cd4af66fa687396e757dec650f28025f2a2f5a5531a3208dc0ec43f2/charset_normalizer-3.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394", size = 208425, upload-time = "2025-10-14T04:40:53.353Z" }, + { url = "https://files.pythonhosted.org/packages/9d/6a/04130023fef2a0d9c62d0bae2649b69f7b7d8d24ea5536feef50551029df/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25", size = 148162, upload-time = "2025-10-14T04:40:54.558Z" }, + { url = "https://files.pythonhosted.org/packages/78/29/62328d79aa60da22c9e0b9a66539feae06ca0f5a4171ac4f7dc285b83688/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef", size = 144558, upload-time = "2025-10-14T04:40:55.677Z" }, + { url = "https://files.pythonhosted.org/packages/86/bb/b32194a4bf15b88403537c2e120b817c61cd4ecffa9b6876e941c3ee38fe/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d", size = 161497, upload-time = "2025-10-14T04:40:57.217Z" }, + { url = "https://files.pythonhosted.org/packages/19/89/a54c82b253d5b9b111dc74aca196ba5ccfcca8242d0fb64146d4d3183ff1/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8", size = 159240, upload-time = "2025-10-14T04:40:58.358Z" }, + { url = "https://files.pythonhosted.org/packages/c0/10/d20b513afe03acc89ec33948320a5544d31f21b05368436d580dec4e234d/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86", size = 153471, upload-time = "2025-10-14T04:40:59.468Z" }, + { url = "https://files.pythonhosted.org/packages/61/fa/fbf177b55bdd727010f9c0a3c49eefa1d10f960e5f09d1d887bf93c2e698/charset_normalizer-3.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a", size = 150864, upload-time = "2025-10-14T04:41:00.623Z" }, + { url = "https://files.pythonhosted.org/packages/05/12/9fbc6a4d39c0198adeebbde20b619790e9236557ca59fc40e0e3cebe6f40/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f", size = 150647, upload-time = "2025-10-14T04:41:01.754Z" }, + { url = "https://files.pythonhosted.org/packages/ad/1f/6a9a593d52e3e8c5d2b167daf8c6b968808efb57ef4c210acb907c365bc4/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc", size = 145110, upload-time = "2025-10-14T04:41:03.231Z" }, + { url = "https://files.pythonhosted.org/packages/30/42/9a52c609e72471b0fc54386dc63c3781a387bb4fe61c20231a4ebcd58bdd/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf", size = 162839, upload-time = "2025-10-14T04:41:04.715Z" }, + { url = "https://files.pythonhosted.org/packages/c4/5b/c0682bbf9f11597073052628ddd38344a3d673fda35a36773f7d19344b23/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15", size = 150667, upload-time = "2025-10-14T04:41:05.827Z" }, + { url = "https://files.pythonhosted.org/packages/e4/24/a41afeab6f990cf2daf6cb8c67419b63b48cf518e4f56022230840c9bfb2/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9", size = 160535, upload-time = "2025-10-14T04:41:06.938Z" }, + { url = "https://files.pythonhosted.org/packages/2a/e5/6a4ce77ed243c4a50a1fecca6aaaab419628c818a49434be428fe24c9957/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0", size = 154816, upload-time = "2025-10-14T04:41:08.101Z" }, + { url = "https://files.pythonhosted.org/packages/a8/ef/89297262b8092b312d29cdb2517cb1237e51db8ecef2e9af5edbe7b683b1/charset_normalizer-3.4.4-cp312-cp312-win32.whl", hash = "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26", size = 99694, upload-time = "2025-10-14T04:41:09.23Z" }, + { url = "https://files.pythonhosted.org/packages/3d/2d/1e5ed9dd3b3803994c155cd9aacb60c82c331bad84daf75bcb9c91b3295e/charset_normalizer-3.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525", size = 107131, upload-time = "2025-10-14T04:41:10.467Z" }, + { url = "https://files.pythonhosted.org/packages/d0/d9/0ed4c7098a861482a7b6a95603edce4c0d9db2311af23da1fb2b75ec26fc/charset_normalizer-3.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3", size = 100390, upload-time = "2025-10-14T04:41:11.915Z" }, + { url = "https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", size = 208091, upload-time = "2025-10-14T04:41:13.346Z" }, + { url = "https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", size = 147936, upload-time = "2025-10-14T04:41:14.461Z" }, + { url = "https://files.pythonhosted.org/packages/89/c5/adb8c8b3d6625bef6d88b251bbb0d95f8205831b987631ab0c8bb5d937c2/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", size = 144180, upload-time = "2025-10-14T04:41:15.588Z" }, + { url = "https://files.pythonhosted.org/packages/91/ed/9706e4070682d1cc219050b6048bfd293ccf67b3d4f5a4f39207453d4b99/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328", size = 161346, upload-time = "2025-10-14T04:41:16.738Z" }, + { url = "https://files.pythonhosted.org/packages/d5/0d/031f0d95e4972901a2f6f09ef055751805ff541511dc1252ba3ca1f80cf5/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede", size = 158874, upload-time = "2025-10-14T04:41:17.923Z" }, + { url = "https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894", size = 153076, upload-time = "2025-10-14T04:41:19.106Z" }, + { url = "https://files.pythonhosted.org/packages/75/1e/5ff781ddf5260e387d6419959ee89ef13878229732732ee73cdae01800f2/charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1", size = 150601, upload-time = "2025-10-14T04:41:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/d7/57/71be810965493d3510a6ca79b90c19e48696fb1ff964da319334b12677f0/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490", size = 150376, upload-time = "2025-10-14T04:41:21.398Z" }, + { url = "https://files.pythonhosted.org/packages/e5/d5/c3d057a78c181d007014feb7e9f2e65905a6c4ef182c0ddf0de2924edd65/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44", size = 144825, upload-time = "2025-10-14T04:41:22.583Z" }, + { url = "https://files.pythonhosted.org/packages/e6/8c/d0406294828d4976f275ffbe66f00266c4b3136b7506941d87c00cab5272/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133", size = 162583, upload-time = "2025-10-14T04:41:23.754Z" }, + { url = "https://files.pythonhosted.org/packages/d7/24/e2aa1f18c8f15c4c0e932d9287b8609dd30ad56dbe41d926bd846e22fb8d/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3", size = 150366, upload-time = "2025-10-14T04:41:25.27Z" }, + { url = "https://files.pythonhosted.org/packages/e4/5b/1e6160c7739aad1e2df054300cc618b06bf784a7a164b0f238360721ab86/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e", size = 160300, upload-time = "2025-10-14T04:41:26.725Z" }, + { url = "https://files.pythonhosted.org/packages/7a/10/f882167cd207fbdd743e55534d5d9620e095089d176d55cb22d5322f2afd/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc", size = 154465, upload-time = "2025-10-14T04:41:28.322Z" }, + { url = "https://files.pythonhosted.org/packages/89/66/c7a9e1b7429be72123441bfdbaf2bc13faab3f90b933f664db506dea5915/charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac", size = 99404, upload-time = "2025-10-14T04:41:29.95Z" }, + { url = "https://files.pythonhosted.org/packages/c4/26/b9924fa27db384bdcd97ab83b4f0a8058d96ad9626ead570674d5e737d90/charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14", size = 107092, upload-time = "2025-10-14T04:41:31.188Z" }, + { url = "https://files.pythonhosted.org/packages/af/8f/3ed4bfa0c0c72a7ca17f0380cd9e4dd842b09f664e780c13cff1dcf2ef1b/charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2", size = 100408, upload-time = "2025-10-14T04:41:32.624Z" }, { url = "https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd", size = 207746, upload-time = "2025-10-14T04:41:33.773Z" }, { url = "https://files.pythonhosted.org/packages/10/9a/97c8d48ef10d6cd4fcead2415523221624bf58bcf68a802721a6bc807c8f/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb", size = 147889, upload-time = "2025-10-14T04:41:34.897Z" }, { url = "https://files.pythonhosted.org/packages/10/bf/979224a919a1b606c82bd2c5fa49b5c6d5727aa47b4312bb27b1734f53cd/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e", size = 143641, upload-time = "2025-10-14T04:41:36.116Z" }, @@ -449,6 +544,9 @@ wheels = [ name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" }, @@ -507,6 +605,28 @@ version = "0.14.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/c3/7d/d9daedf0f2ebcacd20d599928f8913e9d2aea1d56d2d355a93bfa2b611d7/fastuuid-0.14.0.tar.gz", hash = "sha256:178947fc2f995b38497a74172adee64fdeb8b7ec18f2a5934d037641ba265d26", size = 18232, upload-time = "2025-10-19T22:19:22.402Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/02/a2/e78fcc5df65467f0d207661b7ef86c5b7ac62eea337c0c0fcedbeee6fb13/fastuuid-0.14.0-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:77e94728324b63660ebf8adb27055e92d2e4611645bf12ed9d88d30486471d0a", size = 510164, upload-time = "2025-10-19T22:31:45.635Z" }, + { url = "https://files.pythonhosted.org/packages/2b/b3/c846f933f22f581f558ee63f81f29fa924acd971ce903dab1a9b6701816e/fastuuid-0.14.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:caa1f14d2102cb8d353096bc6ef6c13b2c81f347e6ab9d6fbd48b9dea41c153d", size = 261837, upload-time = "2025-10-19T22:38:38.53Z" }, + { url = "https://files.pythonhosted.org/packages/54/ea/682551030f8c4fa9a769d9825570ad28c0c71e30cf34020b85c1f7ee7382/fastuuid-0.14.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d23ef06f9e67163be38cece704170486715b177f6baae338110983f99a72c070", size = 251370, upload-time = "2025-10-19T22:40:26.07Z" }, + { url = "https://files.pythonhosted.org/packages/14/dd/5927f0a523d8e6a76b70968e6004966ee7df30322f5fc9b6cdfb0276646a/fastuuid-0.14.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c9ec605ace243b6dbe3bd27ebdd5d33b00d8d1d3f580b39fdd15cd96fd71796", size = 277766, upload-time = "2025-10-19T22:37:23.779Z" }, + { url = "https://files.pythonhosted.org/packages/16/6e/c0fb547eef61293153348f12e0f75a06abb322664b34a1573a7760501336/fastuuid-0.14.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:808527f2407f58a76c916d6aa15d58692a4a019fdf8d4c32ac7ff303b7d7af09", size = 278105, upload-time = "2025-10-19T22:26:56.821Z" }, + { url = "https://files.pythonhosted.org/packages/2d/b1/b9c75e03b768f61cf2e84ee193dc18601aeaf89a4684b20f2f0e9f52b62c/fastuuid-0.14.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2fb3c0d7fef6674bbeacdd6dbd386924a7b60b26de849266d1ff6602937675c8", size = 301564, upload-time = "2025-10-19T22:30:31.604Z" }, + { url = "https://files.pythonhosted.org/packages/fc/fa/f7395fdac07c7a54f18f801744573707321ca0cee082e638e36452355a9d/fastuuid-0.14.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab3f5d36e4393e628a4df337c2c039069344db5f4b9d2a3c9cea48284f1dd741", size = 459659, upload-time = "2025-10-19T22:31:32.341Z" }, + { url = "https://files.pythonhosted.org/packages/66/49/c9fd06a4a0b1f0f048aacb6599e7d96e5d6bc6fa680ed0d46bf111929d1b/fastuuid-0.14.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:b9a0ca4f03b7e0b01425281ffd44e99d360e15c895f1907ca105854ed85e2057", size = 478430, upload-time = "2025-10-19T22:26:22.962Z" }, + { url = "https://files.pythonhosted.org/packages/be/9c/909e8c95b494e8e140e8be6165d5fc3f61fdc46198c1554df7b3e1764471/fastuuid-0.14.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3acdf655684cc09e60fb7e4cf524e8f42ea760031945aa8086c7eae2eeeabeb8", size = 450894, upload-time = "2025-10-19T22:27:01.647Z" }, + { url = "https://files.pythonhosted.org/packages/90/eb/d29d17521976e673c55ef7f210d4cdd72091a9ec6755d0fd4710d9b3c871/fastuuid-0.14.0-cp312-cp312-win32.whl", hash = "sha256:9579618be6280700ae36ac42c3efd157049fe4dd40ca49b021280481c78c3176", size = 154374, upload-time = "2025-10-19T22:29:19.879Z" }, + { url = "https://files.pythonhosted.org/packages/cc/fc/f5c799a6ea6d877faec0472d0b27c079b47c86b1cdc577720a5386483b36/fastuuid-0.14.0-cp312-cp312-win_amd64.whl", hash = "sha256:d9e4332dc4ba054434a9594cbfaf7823b57993d7d8e7267831c3e059857cf397", size = 156550, upload-time = "2025-10-19T22:27:49.658Z" }, + { url = "https://files.pythonhosted.org/packages/a5/83/ae12dd39b9a39b55d7f90abb8971f1a5f3c321fd72d5aa83f90dc67fe9ed/fastuuid-0.14.0-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:77a09cb7427e7af74c594e409f7731a0cf887221de2f698e1ca0ebf0f3139021", size = 510720, upload-time = "2025-10-19T22:42:34.633Z" }, + { url = "https://files.pythonhosted.org/packages/53/b0/a4b03ff5d00f563cc7546b933c28cb3f2a07344b2aec5834e874f7d44143/fastuuid-0.14.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:9bd57289daf7b153bfa3e8013446aa144ce5e8c825e9e366d455155ede5ea2dc", size = 262024, upload-time = "2025-10-19T22:30:25.482Z" }, + { url = "https://files.pythonhosted.org/packages/9c/6d/64aee0a0f6a58eeabadd582e55d0d7d70258ffdd01d093b30c53d668303b/fastuuid-0.14.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ac60fc860cdf3c3f327374db87ab8e064c86566ca8c49d2e30df15eda1b0c2d5", size = 251679, upload-time = "2025-10-19T22:36:14.096Z" }, + { url = "https://files.pythonhosted.org/packages/60/f5/a7e9cda8369e4f7919d36552db9b2ae21db7915083bc6336f1b0082c8b2e/fastuuid-0.14.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab32f74bd56565b186f036e33129da77db8be09178cd2f5206a5d4035fb2a23f", size = 277862, upload-time = "2025-10-19T22:36:23.302Z" }, + { url = "https://files.pythonhosted.org/packages/f0/d3/8ce11827c783affffd5bd4d6378b28eb6cc6d2ddf41474006b8d62e7448e/fastuuid-0.14.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33e678459cf4addaedd9936bbb038e35b3f6b2061330fd8f2f6a1d80414c0f87", size = 278278, upload-time = "2025-10-19T22:29:43.809Z" }, + { url = "https://files.pythonhosted.org/packages/a2/51/680fb6352d0bbade04036da46264a8001f74b7484e2fd1f4da9e3db1c666/fastuuid-0.14.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1e3cc56742f76cd25ecb98e4b82a25f978ccffba02e4bdce8aba857b6d85d87b", size = 301788, upload-time = "2025-10-19T22:36:06.825Z" }, + { url = "https://files.pythonhosted.org/packages/fa/7c/2014b5785bd8ebdab04ec857635ebd84d5ee4950186a577db9eff0fb8ff6/fastuuid-0.14.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:cb9a030f609194b679e1660f7e32733b7a0f332d519c5d5a6a0a580991290022", size = 459819, upload-time = "2025-10-19T22:35:31.623Z" }, + { url = "https://files.pythonhosted.org/packages/01/d2/524d4ceeba9160e7a9bc2ea3e8f4ccf1ad78f3bde34090ca0c51f09a5e91/fastuuid-0.14.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:09098762aad4f8da3a888eb9ae01c84430c907a297b97166b8abc07b640f2995", size = 478546, upload-time = "2025-10-19T22:26:03.023Z" }, + { url = "https://files.pythonhosted.org/packages/bc/17/354d04951ce114bf4afc78e27a18cfbd6ee319ab1829c2d5fb5e94063ac6/fastuuid-0.14.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:1383fff584fa249b16329a059c68ad45d030d5a4b70fb7c73a08d98fd53bcdab", size = 450921, upload-time = "2025-10-19T22:31:02.151Z" }, + { url = "https://files.pythonhosted.org/packages/fb/be/d7be8670151d16d88f15bb121c5b66cdb5ea6a0c2a362d0dcf30276ade53/fastuuid-0.14.0-cp313-cp313-win32.whl", hash = "sha256:a0809f8cc5731c066c909047f9a314d5f536c871a7a22e815cc4967c110ac9ad", size = 154559, upload-time = "2025-10-19T22:36:36.011Z" }, + { url = "https://files.pythonhosted.org/packages/22/1d/5573ef3624ceb7abf4a46073d3554e37191c868abc3aecd5289a72f9810a/fastuuid-0.14.0-cp313-cp313-win_amd64.whl", hash = "sha256:0df14e92e7ad3276327631c9e7cec09e32572ce82089c55cb1bb8df71cf394ed", size = 156539, upload-time = "2025-10-19T22:33:35.898Z" }, { url = "https://files.pythonhosted.org/packages/16/c9/8c7660d1fe3862e3f8acabd9be7fc9ad71eb270f1c65cce9a2b7a31329ab/fastuuid-0.14.0-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:b852a870a61cfc26c884af205d502881a2e59cc07076b60ab4a951cc0c94d1ad", size = 510600, upload-time = "2025-10-19T22:43:44.17Z" }, { url = "https://files.pythonhosted.org/packages/4c/f4/a989c82f9a90d0ad995aa957b3e572ebef163c5299823b4027986f133dfb/fastuuid-0.14.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:c7502d6f54cd08024c3ea9b3514e2d6f190feb2f46e6dbcd3747882264bb5f7b", size = 262069, upload-time = "2025-10-19T22:43:38.38Z" }, { url = "https://files.pythonhosted.org/packages/da/6c/a1a24f73574ac995482b1326cf7ab41301af0fabaa3e37eeb6b3df00e6e2/fastuuid-0.14.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1ca61b592120cf314cfd66e662a5b54a578c5a15b26305e1b8b618a6f22df714", size = 251543, upload-time = "2025-10-19T22:32:22.537Z" }, @@ -535,6 +655,54 @@ version = "1.8.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/2d/f5/c831fac6cc817d26fd54c7eaccd04ef7e0288806943f7cc5bbf69f3ac1f0/frozenlist-1.8.0.tar.gz", hash = "sha256:3ede829ed8d842f6cd48fc7081d7a41001a56f1f38603f9d49bf3020d59a31ad", size = 45875, upload-time = "2025-10-06T05:38:17.865Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/69/29/948b9aa87e75820a38650af445d2ef2b6b8a6fab1a23b6bb9e4ef0be2d59/frozenlist-1.8.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:78f7b9e5d6f2fdb88cdde9440dc147259b62b9d3b019924def9f6478be254ac1", size = 87782, upload-time = "2025-10-06T05:36:06.649Z" }, + { url = "https://files.pythonhosted.org/packages/64/80/4f6e318ee2a7c0750ed724fa33a4bdf1eacdc5a39a7a24e818a773cd91af/frozenlist-1.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:229bf37d2e4acdaf808fd3f06e854a4a7a3661e871b10dc1f8f1896a3b05f18b", size = 50594, upload-time = "2025-10-06T05:36:07.69Z" }, + { url = "https://files.pythonhosted.org/packages/2b/94/5c8a2b50a496b11dd519f4a24cb5496cf125681dd99e94c604ccdea9419a/frozenlist-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f833670942247a14eafbb675458b4e61c82e002a148f49e68257b79296e865c4", size = 50448, upload-time = "2025-10-06T05:36:08.78Z" }, + { url = "https://files.pythonhosted.org/packages/6a/bd/d91c5e39f490a49df14320f4e8c80161cfcce09f1e2cde1edd16a551abb3/frozenlist-1.8.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:494a5952b1c597ba44e0e78113a7266e656b9794eec897b19ead706bd7074383", size = 242411, upload-time = "2025-10-06T05:36:09.801Z" }, + { url = "https://files.pythonhosted.org/packages/8f/83/f61505a05109ef3293dfb1ff594d13d64a2324ac3482be2cedc2be818256/frozenlist-1.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96f423a119f4777a4a056b66ce11527366a8bb92f54e541ade21f2374433f6d4", size = 243014, upload-time = "2025-10-06T05:36:11.394Z" }, + { url = "https://files.pythonhosted.org/packages/d8/cb/cb6c7b0f7d4023ddda30cf56b8b17494eb3a79e3fda666bf735f63118b35/frozenlist-1.8.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3462dd9475af2025c31cc61be6652dfa25cbfb56cbbf52f4ccfe029f38decaf8", size = 234909, upload-time = "2025-10-06T05:36:12.598Z" }, + { url = "https://files.pythonhosted.org/packages/31/c5/cd7a1f3b8b34af009fb17d4123c5a778b44ae2804e3ad6b86204255f9ec5/frozenlist-1.8.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4c800524c9cd9bac5166cd6f55285957fcfc907db323e193f2afcd4d9abd69b", size = 250049, upload-time = "2025-10-06T05:36:14.065Z" }, + { url = "https://files.pythonhosted.org/packages/c0/01/2f95d3b416c584a1e7f0e1d6d31998c4a795f7544069ee2e0962a4b60740/frozenlist-1.8.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d6a5df73acd3399d893dafc71663ad22534b5aa4f94e8a2fabfe856c3c1b6a52", size = 256485, upload-time = "2025-10-06T05:36:15.39Z" }, + { url = "https://files.pythonhosted.org/packages/ce/03/024bf7720b3abaebcff6d0793d73c154237b85bdf67b7ed55e5e9596dc9a/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:405e8fe955c2280ce66428b3ca55e12b3c4e9c336fb2103a4937e891c69a4a29", size = 237619, upload-time = "2025-10-06T05:36:16.558Z" }, + { url = "https://files.pythonhosted.org/packages/69/fa/f8abdfe7d76b731f5d8bd217827cf6764d4f1d9763407e42717b4bed50a0/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:908bd3f6439f2fef9e85031b59fd4f1297af54415fb60e4254a95f75b3cab3f3", size = 250320, upload-time = "2025-10-06T05:36:17.821Z" }, + { url = "https://files.pythonhosted.org/packages/f5/3c/b051329f718b463b22613e269ad72138cc256c540f78a6de89452803a47d/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:294e487f9ec720bd8ffcebc99d575f7eff3568a08a253d1ee1a0378754b74143", size = 246820, upload-time = "2025-10-06T05:36:19.046Z" }, + { url = "https://files.pythonhosted.org/packages/0f/ae/58282e8f98e444b3f4dd42448ff36fa38bef29e40d40f330b22e7108f565/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:74c51543498289c0c43656701be6b077f4b265868fa7f8a8859c197006efb608", size = 250518, upload-time = "2025-10-06T05:36:20.763Z" }, + { url = "https://files.pythonhosted.org/packages/8f/96/007e5944694d66123183845a106547a15944fbbb7154788cbf7272789536/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:776f352e8329135506a1d6bf16ac3f87bc25b28e765949282dcc627af36123aa", size = 239096, upload-time = "2025-10-06T05:36:22.129Z" }, + { url = "https://files.pythonhosted.org/packages/66/bb/852b9d6db2fa40be96f29c0d1205c306288f0684df8fd26ca1951d461a56/frozenlist-1.8.0-cp312-cp312-win32.whl", hash = "sha256:433403ae80709741ce34038da08511d4a77062aa924baf411ef73d1146e74faf", size = 39985, upload-time = "2025-10-06T05:36:23.661Z" }, + { url = "https://files.pythonhosted.org/packages/b8/af/38e51a553dd66eb064cdf193841f16f077585d4d28394c2fa6235cb41765/frozenlist-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:34187385b08f866104f0c0617404c8eb08165ab1272e884abc89c112e9c00746", size = 44591, upload-time = "2025-10-06T05:36:24.958Z" }, + { url = "https://files.pythonhosted.org/packages/a7/06/1dc65480ab147339fecc70797e9c2f69d9cea9cf38934ce08df070fdb9cb/frozenlist-1.8.0-cp312-cp312-win_arm64.whl", hash = "sha256:fe3c58d2f5db5fbd18c2987cba06d51b0529f52bc3a6cdc33d3f4eab725104bd", size = 40102, upload-time = "2025-10-06T05:36:26.333Z" }, + { url = "https://files.pythonhosted.org/packages/2d/40/0832c31a37d60f60ed79e9dfb5a92e1e2af4f40a16a29abcc7992af9edff/frozenlist-1.8.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8d92f1a84bb12d9e56f818b3a746f3efba93c1b63c8387a73dde655e1e42282a", size = 85717, upload-time = "2025-10-06T05:36:27.341Z" }, + { url = "https://files.pythonhosted.org/packages/30/ba/b0b3de23f40bc55a7057bd38434e25c34fa48e17f20ee273bbde5e0650f3/frozenlist-1.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:96153e77a591c8adc2ee805756c61f59fef4cf4073a9275ee86fe8cba41241f7", size = 49651, upload-time = "2025-10-06T05:36:28.855Z" }, + { url = "https://files.pythonhosted.org/packages/0c/ab/6e5080ee374f875296c4243c381bbdef97a9ac39c6e3ce1d5f7d42cb78d6/frozenlist-1.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f21f00a91358803399890ab167098c131ec2ddd5f8f5fd5fe9c9f2c6fcd91e40", size = 49417, upload-time = "2025-10-06T05:36:29.877Z" }, + { url = "https://files.pythonhosted.org/packages/d5/4e/e4691508f9477ce67da2015d8c00acd751e6287739123113a9fca6f1604e/frozenlist-1.8.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fb30f9626572a76dfe4293c7194a09fb1fe93ba94c7d4f720dfae3b646b45027", size = 234391, upload-time = "2025-10-06T05:36:31.301Z" }, + { url = "https://files.pythonhosted.org/packages/40/76/c202df58e3acdf12969a7895fd6f3bc016c642e6726aa63bd3025e0fc71c/frozenlist-1.8.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eaa352d7047a31d87dafcacbabe89df0aa506abb5b1b85a2fb91bc3faa02d822", size = 233048, upload-time = "2025-10-06T05:36:32.531Z" }, + { url = "https://files.pythonhosted.org/packages/f9/c0/8746afb90f17b73ca5979c7a3958116e105ff796e718575175319b5bb4ce/frozenlist-1.8.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:03ae967b4e297f58f8c774c7eabcce57fe3c2434817d4385c50661845a058121", size = 226549, upload-time = "2025-10-06T05:36:33.706Z" }, + { url = "https://files.pythonhosted.org/packages/7e/eb/4c7eefc718ff72f9b6c4893291abaae5fbc0c82226a32dcd8ef4f7a5dbef/frozenlist-1.8.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f6292f1de555ffcc675941d65fffffb0a5bcd992905015f85d0592201793e0e5", size = 239833, upload-time = "2025-10-06T05:36:34.947Z" }, + { url = "https://files.pythonhosted.org/packages/c2/4e/e5c02187cf704224f8b21bee886f3d713ca379535f16893233b9d672ea71/frozenlist-1.8.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29548f9b5b5e3460ce7378144c3010363d8035cea44bc0bf02d57f5a685e084e", size = 245363, upload-time = "2025-10-06T05:36:36.534Z" }, + { url = "https://files.pythonhosted.org/packages/1f/96/cb85ec608464472e82ad37a17f844889c36100eed57bea094518bf270692/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ec3cc8c5d4084591b4237c0a272cc4f50a5b03396a47d9caaf76f5d7b38a4f11", size = 229314, upload-time = "2025-10-06T05:36:38.582Z" }, + { url = "https://files.pythonhosted.org/packages/5d/6f/4ae69c550e4cee66b57887daeebe006fe985917c01d0fff9caab9883f6d0/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:517279f58009d0b1f2e7c1b130b377a349405da3f7621ed6bfae50b10adf20c1", size = 243365, upload-time = "2025-10-06T05:36:40.152Z" }, + { url = "https://files.pythonhosted.org/packages/7a/58/afd56de246cf11780a40a2c28dc7cbabbf06337cc8ddb1c780a2d97e88d8/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:db1e72ede2d0d7ccb213f218df6a078a9c09a7de257c2fe8fcef16d5925230b1", size = 237763, upload-time = "2025-10-06T05:36:41.355Z" }, + { url = "https://files.pythonhosted.org/packages/cb/36/cdfaf6ed42e2644740d4a10452d8e97fa1c062e2a8006e4b09f1b5fd7d63/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b4dec9482a65c54a5044486847b8a66bf10c9cb4926d42927ec4e8fd5db7fed8", size = 240110, upload-time = "2025-10-06T05:36:42.716Z" }, + { url = "https://files.pythonhosted.org/packages/03/a8/9ea226fbefad669f11b52e864c55f0bd57d3c8d7eb07e9f2e9a0b39502e1/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:21900c48ae04d13d416f0e1e0c4d81f7931f73a9dfa0b7a8746fb2fe7dd970ed", size = 233717, upload-time = "2025-10-06T05:36:44.251Z" }, + { url = "https://files.pythonhosted.org/packages/1e/0b/1b5531611e83ba7d13ccc9988967ea1b51186af64c42b7a7af465dcc9568/frozenlist-1.8.0-cp313-cp313-win32.whl", hash = "sha256:8b7b94a067d1c504ee0b16def57ad5738701e4ba10cec90529f13fa03c833496", size = 39628, upload-time = "2025-10-06T05:36:45.423Z" }, + { url = "https://files.pythonhosted.org/packages/d8/cf/174c91dbc9cc49bc7b7aab74d8b734e974d1faa8f191c74af9b7e80848e6/frozenlist-1.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:878be833caa6a3821caf85eb39c5ba92d28e85df26d57afb06b35b2efd937231", size = 43882, upload-time = "2025-10-06T05:36:46.796Z" }, + { url = "https://files.pythonhosted.org/packages/c1/17/502cd212cbfa96eb1388614fe39a3fc9ab87dbbe042b66f97acb57474834/frozenlist-1.8.0-cp313-cp313-win_arm64.whl", hash = "sha256:44389d135b3ff43ba8cc89ff7f51f5a0bb6b63d829c8300f79a2fe4fe61bcc62", size = 39676, upload-time = "2025-10-06T05:36:47.8Z" }, + { url = "https://files.pythonhosted.org/packages/d2/5c/3bbfaa920dfab09e76946a5d2833a7cbdf7b9b4a91c714666ac4855b88b4/frozenlist-1.8.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:e25ac20a2ef37e91c1b39938b591457666a0fa835c7783c3a8f33ea42870db94", size = 89235, upload-time = "2025-10-06T05:36:48.78Z" }, + { url = "https://files.pythonhosted.org/packages/d2/d6/f03961ef72166cec1687e84e8925838442b615bd0b8854b54923ce5b7b8a/frozenlist-1.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07cdca25a91a4386d2e76ad992916a85038a9b97561bf7a3fd12d5d9ce31870c", size = 50742, upload-time = "2025-10-06T05:36:49.837Z" }, + { url = "https://files.pythonhosted.org/packages/1e/bb/a6d12b7ba4c3337667d0e421f7181c82dda448ce4e7ad7ecd249a16fa806/frozenlist-1.8.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4e0c11f2cc6717e0a741f84a527c52616140741cd812a50422f83dc31749fb52", size = 51725, upload-time = "2025-10-06T05:36:50.851Z" }, + { url = "https://files.pythonhosted.org/packages/bc/71/d1fed0ffe2c2ccd70b43714c6cab0f4188f09f8a67a7914a6b46ee30f274/frozenlist-1.8.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b3210649ee28062ea6099cfda39e147fa1bc039583c8ee4481cb7811e2448c51", size = 284533, upload-time = "2025-10-06T05:36:51.898Z" }, + { url = "https://files.pythonhosted.org/packages/c9/1f/fb1685a7b009d89f9bf78a42d94461bc06581f6e718c39344754a5d9bada/frozenlist-1.8.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:581ef5194c48035a7de2aefc72ac6539823bb71508189e5de01d60c9dcd5fa65", size = 292506, upload-time = "2025-10-06T05:36:53.101Z" }, + { url = "https://files.pythonhosted.org/packages/e6/3b/b991fe1612703f7e0d05c0cf734c1b77aaf7c7d321df4572e8d36e7048c8/frozenlist-1.8.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3ef2d026f16a2b1866e1d86fc4e1291e1ed8a387b2c333809419a2f8b3a77b82", size = 274161, upload-time = "2025-10-06T05:36:54.309Z" }, + { url = "https://files.pythonhosted.org/packages/ca/ec/c5c618767bcdf66e88945ec0157d7f6c4a1322f1473392319b7a2501ded7/frozenlist-1.8.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5500ef82073f599ac84d888e3a8c1f77ac831183244bfd7f11eaa0289fb30714", size = 294676, upload-time = "2025-10-06T05:36:55.566Z" }, + { url = "https://files.pythonhosted.org/packages/7c/ce/3934758637d8f8a88d11f0585d6495ef54b2044ed6ec84492a91fa3b27aa/frozenlist-1.8.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:50066c3997d0091c411a66e710f4e11752251e6d2d73d70d8d5d4c76442a199d", size = 300638, upload-time = "2025-10-06T05:36:56.758Z" }, + { url = "https://files.pythonhosted.org/packages/fc/4f/a7e4d0d467298f42de4b41cbc7ddaf19d3cfeabaf9ff97c20c6c7ee409f9/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5c1c8e78426e59b3f8005e9b19f6ff46e5845895adbde20ece9218319eca6506", size = 283067, upload-time = "2025-10-06T05:36:57.965Z" }, + { url = "https://files.pythonhosted.org/packages/dc/48/c7b163063d55a83772b268e6d1affb960771b0e203b632cfe09522d67ea5/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:eefdba20de0d938cec6a89bd4d70f346a03108a19b9df4248d3cf0d88f1b0f51", size = 292101, upload-time = "2025-10-06T05:36:59.237Z" }, + { url = "https://files.pythonhosted.org/packages/9f/d0/2366d3c4ecdc2fd391e0afa6e11500bfba0ea772764d631bbf82f0136c9d/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:cf253e0e1c3ceb4aaff6df637ce033ff6535fb8c70a764a8f46aafd3d6ab798e", size = 289901, upload-time = "2025-10-06T05:37:00.811Z" }, + { url = "https://files.pythonhosted.org/packages/b8/94/daff920e82c1b70e3618a2ac39fbc01ae3e2ff6124e80739ce5d71c9b920/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:032efa2674356903cd0261c4317a561a6850f3ac864a63fc1583147fb05a79b0", size = 289395, upload-time = "2025-10-06T05:37:02.115Z" }, + { url = "https://files.pythonhosted.org/packages/e3/20/bba307ab4235a09fdcd3cc5508dbabd17c4634a1af4b96e0f69bfe551ebd/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6da155091429aeba16851ecb10a9104a108bcd32f6c1642867eadaee401c1c41", size = 283659, upload-time = "2025-10-06T05:37:03.711Z" }, + { url = "https://files.pythonhosted.org/packages/fd/00/04ca1c3a7a124b6de4f8a9a17cc2fcad138b4608e7a3fc5877804b8715d7/frozenlist-1.8.0-cp313-cp313t-win32.whl", hash = "sha256:0f96534f8bfebc1a394209427d0f8a63d343c9779cda6fc25e8e121b5fd8555b", size = 43492, upload-time = "2025-10-06T05:37:04.915Z" }, + { url = "https://files.pythonhosted.org/packages/59/5e/c69f733a86a94ab10f68e496dc6b7e8bc078ebb415281d5698313e3af3a1/frozenlist-1.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:5d63a068f978fc69421fb0e6eb91a9603187527c86b7cd3f534a5b77a592b888", size = 48034, upload-time = "2025-10-06T05:37:06.343Z" }, + { url = "https://files.pythonhosted.org/packages/16/6c/be9d79775d8abe79b05fa6d23da99ad6e7763a1d080fbae7290b286093fd/frozenlist-1.8.0-cp313-cp313t-win_arm64.whl", hash = "sha256:bf0a7e10b077bf5fb9380ad3ae8ce20ef919a6ad93b4552896419ac7e1d8e042", size = 41749, upload-time = "2025-10-06T05:37:07.431Z" }, { url = "https://files.pythonhosted.org/packages/f1/c8/85da824b7e7b9b6e7f7705b2ecaf9591ba6f79c1177f324c2735e41d36a2/frozenlist-1.8.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cee686f1f4cadeb2136007ddedd0aaf928ab95216e7691c63e50a8ec066336d0", size = 86127, upload-time = "2025-10-06T05:37:08.438Z" }, { url = "https://files.pythonhosted.org/packages/8e/e8/a1185e236ec66c20afd72399522f142c3724c785789255202d27ae992818/frozenlist-1.8.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:119fb2a1bd47307e899c2fac7f28e85b9a543864df47aa7ec9d3c1b4545f096f", size = 49698, upload-time = "2025-10-06T05:37:09.48Z" }, { url = "https://files.pythonhosted.org/packages/a1/93/72b1736d68f03fda5fdf0f2180fb6caaae3894f1b854d006ac61ecc727ee/frozenlist-1.8.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4970ece02dbc8c3a92fcc5228e36a3e933a01a999f7094ff7c23fbd2beeaa67c", size = 49749, upload-time = "2025-10-06T05:37:10.569Z" }, @@ -594,6 +762,13 @@ version = "1.2.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/5e/6e/0f11bacf08a67f7fb5ee09740f2ca54163863b07b70d579356e9222ce5d8/hf_xet-1.2.0.tar.gz", hash = "sha256:a8c27070ca547293b6890c4bf389f713f80e8c478631432962bb7f4bc0bd7d7f", size = 506020, upload-time = "2025-10-24T19:04:32.129Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/a5/85ef910a0aa034a2abcfadc360ab5ac6f6bc4e9112349bd40ca97551cff0/hf_xet-1.2.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:ceeefcd1b7aed4956ae8499e2199607765fbd1c60510752003b6cc0b8413b649", size = 2861870, upload-time = "2025-10-24T19:04:11.422Z" }, + { url = "https://files.pythonhosted.org/packages/ea/40/e2e0a7eb9a51fe8828ba2d47fe22a7e74914ea8a0db68a18c3aa7449c767/hf_xet-1.2.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b70218dd548e9840224df5638fdc94bd033552963cfa97f9170829381179c813", size = 2717584, upload-time = "2025-10-24T19:04:09.586Z" }, + { url = "https://files.pythonhosted.org/packages/a5/7d/daf7f8bc4594fdd59a8a596f9e3886133fdc68e675292218a5e4c1b7e834/hf_xet-1.2.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d40b18769bb9a8bc82a9ede575ce1a44c75eb80e7375a01d76259089529b5dc", size = 3315004, upload-time = "2025-10-24T19:04:00.314Z" }, + { url = "https://files.pythonhosted.org/packages/b1/ba/45ea2f605fbf6d81c8b21e4d970b168b18a53515923010c312c06cd83164/hf_xet-1.2.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:cd3a6027d59cfb60177c12d6424e31f4b5ff13d8e3a1247b3a584bf8977e6df5", size = 3222636, upload-time = "2025-10-24T19:03:58.111Z" }, + { url = "https://files.pythonhosted.org/packages/4a/1d/04513e3cab8f29ab8c109d309ddd21a2705afab9d52f2ba1151e0c14f086/hf_xet-1.2.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6de1fc44f58f6dd937956c8d304d8c2dea264c80680bcfa61ca4a15e7b76780f", size = 3408448, upload-time = "2025-10-24T19:04:20.951Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7c/60a2756d7feec7387db3a1176c632357632fbe7849fce576c5559d4520c7/hf_xet-1.2.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f182f264ed2acd566c514e45da9f2119110e48a87a327ca271027904c70c5832", size = 3503401, upload-time = "2025-10-24T19:04:22.549Z" }, + { url = "https://files.pythonhosted.org/packages/4e/64/48fffbd67fb418ab07451e4ce641a70de1c40c10a13e25325e24858ebe5a/hf_xet-1.2.0-cp313-cp313t-win_amd64.whl", hash = "sha256:293a7a3787e5c95d7be1857358a9130694a9c6021de3f27fa233f37267174382", size = 2900866, upload-time = "2025-10-24T19:04:33.461Z" }, { url = "https://files.pythonhosted.org/packages/e2/51/f7e2caae42f80af886db414d4e9885fac959330509089f97cccb339c6b87/hf_xet-1.2.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:10bfab528b968c70e062607f663e21e34e2bba349e8038db546646875495179e", size = 2861861, upload-time = "2025-10-24T19:04:19.01Z" }, { url = "https://files.pythonhosted.org/packages/6e/1d/a641a88b69994f9371bd347f1dd35e5d1e2e2460a2e350c8d5165fc62005/hf_xet-1.2.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2a212e842647b02eb6a911187dc878e79c4aa0aa397e88dd3b26761676e8c1f8", size = 2717699, upload-time = "2025-10-24T19:04:17.306Z" }, { url = "https://files.pythonhosted.org/packages/df/e0/e5e9bba7d15f0318955f7ec3f4af13f92e773fbb368c0b8008a5acbcb12f/hf_xet-1.2.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:30e06daccb3a7d4c065f34fc26c14c74f4653069bb2b194e7f18f17cbe9939c0", size = 3314885, upload-time = "2025-10-24T19:04:07.642Z" }, @@ -758,6 +933,37 @@ version = "0.13.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/0d/5e/4ec91646aee381d01cdb9974e30882c9cd3b8c5d1079d6b5ff4af522439a/jiter-0.13.0.tar.gz", hash = "sha256:f2839f9c2c7e2dffc1bc5929a510e14ce0a946be9365fd1219e7ef342dae14f4", size = 164847, upload-time = "2026-02-02T12:37:56.441Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/2e/30/7687e4f87086829955013ca12a9233523349767f69653ebc27036313def9/jiter-0.13.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0a2bd69fc1d902e89925fc34d1da51b2128019423d7b339a45d9e99c894e0663", size = 307958, upload-time = "2026-02-02T12:35:57.165Z" }, + { url = "https://files.pythonhosted.org/packages/c3/27/e57f9a783246ed95481e6749cc5002a8a767a73177a83c63ea71f0528b90/jiter-0.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f917a04240ef31898182f76a332f508f2cc4b57d2b4d7ad2dbfebbfe167eb505", size = 318597, upload-time = "2026-02-02T12:35:58.591Z" }, + { url = "https://files.pythonhosted.org/packages/cf/52/e5719a60ac5d4d7c5995461a94ad5ef962a37c8bf5b088390e6fad59b2ff/jiter-0.13.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1e2b199f446d3e82246b4fd9236d7cb502dc2222b18698ba0d986d2fecc6152", size = 348821, upload-time = "2026-02-02T12:36:00.093Z" }, + { url = "https://files.pythonhosted.org/packages/61/db/c1efc32b8ba4c740ab3fc2d037d8753f67685f475e26b9d6536a4322bcdd/jiter-0.13.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:04670992b576fa65bd056dbac0c39fe8bd67681c380cb2b48efa885711d9d726", size = 364163, upload-time = "2026-02-02T12:36:01.937Z" }, + { url = "https://files.pythonhosted.org/packages/55/8a/fb75556236047c8806995671a18e4a0ad646ed255276f51a20f32dceaeec/jiter-0.13.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a1aff1fbdb803a376d4d22a8f63f8e7ccbce0b4890c26cc7af9e501ab339ef0", size = 483709, upload-time = "2026-02-02T12:36:03.41Z" }, + { url = "https://files.pythonhosted.org/packages/7e/16/43512e6ee863875693a8e6f6d532e19d650779d6ba9a81593ae40a9088ff/jiter-0.13.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b3fb8c2053acaef8580809ac1d1f7481a0a0bdc012fd7f5d8b18fb696a5a089", size = 370480, upload-time = "2026-02-02T12:36:04.791Z" }, + { url = "https://files.pythonhosted.org/packages/f8/4c/09b93e30e984a187bc8aaa3510e1ec8dcbdcd71ca05d2f56aac0492453aa/jiter-0.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdaba7d87e66f26a2c45d8cbadcbfc4bf7884182317907baf39cfe9775bb4d93", size = 360735, upload-time = "2026-02-02T12:36:06.994Z" }, + { url = "https://files.pythonhosted.org/packages/1a/1b/46c5e349019874ec5dfa508c14c37e29864ea108d376ae26d90bee238cd7/jiter-0.13.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7b88d649135aca526da172e48083da915ec086b54e8e73a425ba50999468cc08", size = 391814, upload-time = "2026-02-02T12:36:08.368Z" }, + { url = "https://files.pythonhosted.org/packages/15/9e/26184760e85baee7162ad37b7912797d2077718476bf91517641c92b3639/jiter-0.13.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e404ea551d35438013c64b4f357b0474c7abf9f781c06d44fcaf7a14c69ff9e2", size = 513990, upload-time = "2026-02-02T12:36:09.993Z" }, + { url = "https://files.pythonhosted.org/packages/e9/34/2c9355247d6debad57a0a15e76ab1566ab799388042743656e566b3b7de1/jiter-0.13.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1f4748aad1b4a93c8bdd70f604d0f748cdc0e8744c5547798acfa52f10e79228", size = 548021, upload-time = "2026-02-02T12:36:11.376Z" }, + { url = "https://files.pythonhosted.org/packages/ac/4a/9f2c23255d04a834398b9c2e0e665382116911dc4d06b795710503cdad25/jiter-0.13.0-cp312-cp312-win32.whl", hash = "sha256:0bf670e3b1445fc4d31612199f1744f67f889ee1bbae703c4b54dc097e5dd394", size = 203024, upload-time = "2026-02-02T12:36:12.682Z" }, + { url = "https://files.pythonhosted.org/packages/09/ee/f0ae675a957ae5a8f160be3e87acea6b11dc7b89f6b7ab057e77b2d2b13a/jiter-0.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:15db60e121e11fe186c0b15236bd5d18381b9ddacdcf4e659feb96fc6c969c92", size = 205424, upload-time = "2026-02-02T12:36:13.93Z" }, + { url = "https://files.pythonhosted.org/packages/1b/02/ae611edf913d3cbf02c97cdb90374af2082c48d7190d74c1111dde08bcdd/jiter-0.13.0-cp312-cp312-win_arm64.whl", hash = "sha256:41f92313d17989102f3cb5dd533a02787cdb99454d494344b0361355da52fcb9", size = 186818, upload-time = "2026-02-02T12:36:15.308Z" }, + { url = "https://files.pythonhosted.org/packages/91/9c/7ee5a6ff4b9991e1a45263bfc46731634c4a2bde27dfda6c8251df2d958c/jiter-0.13.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1f8a55b848cbabf97d861495cd65f1e5c590246fabca8b48e1747c4dfc8f85bf", size = 306897, upload-time = "2026-02-02T12:36:16.748Z" }, + { url = "https://files.pythonhosted.org/packages/7c/02/be5b870d1d2be5dd6a91bdfb90f248fbb7dcbd21338f092c6b89817c3dbf/jiter-0.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f556aa591c00f2c45eb1b89f68f52441a016034d18b65da60e2d2875bbbf344a", size = 317507, upload-time = "2026-02-02T12:36:18.351Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/b25d2ec333615f5f284f3a4024f7ce68cfa0604c322c6808b2344c7f5d2b/jiter-0.13.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7e1d61da332ec412350463891923f960c3073cf1aae93b538f0bb4c8cd46efb", size = 350560, upload-time = "2026-02-02T12:36:19.746Z" }, + { url = "https://files.pythonhosted.org/packages/be/ec/74dcb99fef0aca9fbe56b303bf79f6bd839010cb18ad41000bf6cc71eec0/jiter-0.13.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3097d665a27bc96fd9bbf7f86178037db139f319f785e4757ce7ccbf390db6c2", size = 363232, upload-time = "2026-02-02T12:36:21.243Z" }, + { url = "https://files.pythonhosted.org/packages/1b/37/f17375e0bb2f6a812d4dd92d7616e41917f740f3e71343627da9db2824ce/jiter-0.13.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d01ecc3a8cbdb6f25a37bd500510550b64ddf9f7d64a107d92f3ccb25035d0f", size = 483727, upload-time = "2026-02-02T12:36:22.688Z" }, + { url = "https://files.pythonhosted.org/packages/77/d2/a71160a5ae1a1e66c1395b37ef77da67513b0adba73b993a27fbe47eb048/jiter-0.13.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ed9bbc30f5d60a3bdf63ae76beb3f9db280d7f195dfcfa61af792d6ce912d159", size = 370799, upload-time = "2026-02-02T12:36:24.106Z" }, + { url = "https://files.pythonhosted.org/packages/01/99/ed5e478ff0eb4e8aa5fd998f9d69603c9fd3f32de3bd16c2b1194f68361c/jiter-0.13.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98fbafb6e88256f4454de33c1f40203d09fc33ed19162a68b3b257b29ca7f663", size = 359120, upload-time = "2026-02-02T12:36:25.519Z" }, + { url = "https://files.pythonhosted.org/packages/16/be/7ffd08203277a813f732ba897352797fa9493faf8dc7995b31f3d9cb9488/jiter-0.13.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5467696f6b827f1116556cb0db620440380434591e93ecee7fd14d1a491b6daa", size = 390664, upload-time = "2026-02-02T12:36:26.866Z" }, + { url = "https://files.pythonhosted.org/packages/d1/84/e0787856196d6d346264d6dcccb01f741e5f0bd014c1d9a2ebe149caf4f3/jiter-0.13.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:2d08c9475d48b92892583df9da592a0e2ac49bcd41fae1fec4f39ba6cf107820", size = 513543, upload-time = "2026-02-02T12:36:28.217Z" }, + { url = "https://files.pythonhosted.org/packages/65/50/ecbd258181c4313cf79bca6c88fb63207d04d5bf5e4f65174114d072aa55/jiter-0.13.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:aed40e099404721d7fcaf5b89bd3b4568a4666358bcac7b6b15c09fb6252ab68", size = 547262, upload-time = "2026-02-02T12:36:29.678Z" }, + { url = "https://files.pythonhosted.org/packages/27/da/68f38d12e7111d2016cd198161b36e1f042bd115c169255bcb7ec823a3bf/jiter-0.13.0-cp313-cp313-win32.whl", hash = "sha256:36ebfbcffafb146d0e6ffb3e74d51e03d9c35ce7c625c8066cdbfc7b953bdc72", size = 200630, upload-time = "2026-02-02T12:36:31.808Z" }, + { url = "https://files.pythonhosted.org/packages/25/65/3bd1a972c9a08ecd22eb3b08a95d1941ebe6938aea620c246cf426ae09c2/jiter-0.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:8d76029f077379374cf0dbc78dbe45b38dec4a2eb78b08b5194ce836b2517afc", size = 202602, upload-time = "2026-02-02T12:36:33.679Z" }, + { url = "https://files.pythonhosted.org/packages/15/fe/13bd3678a311aa67686bb303654792c48206a112068f8b0b21426eb6851e/jiter-0.13.0-cp313-cp313-win_arm64.whl", hash = "sha256:bb7613e1a427cfcb6ea4544f9ac566b93d5bf67e0d48c787eca673ff9c9dff2b", size = 185939, upload-time = "2026-02-02T12:36:35.065Z" }, + { url = "https://files.pythonhosted.org/packages/49/19/a929ec002ad3228bc97ca01dbb14f7632fffdc84a95ec92ceaf4145688ae/jiter-0.13.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:fa476ab5dd49f3bf3a168e05f89358c75a17608dbabb080ef65f96b27c19ab10", size = 316616, upload-time = "2026-02-02T12:36:36.579Z" }, + { url = "https://files.pythonhosted.org/packages/52/56/d19a9a194afa37c1728831e5fb81b7722c3de18a3109e8f282bfc23e587a/jiter-0.13.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ade8cb6ff5632a62b7dbd4757d8c5573f7a2e9ae285d6b5b841707d8363205ef", size = 346850, upload-time = "2026-02-02T12:36:38.058Z" }, + { url = "https://files.pythonhosted.org/packages/36/4a/94e831c6bf287754a8a019cb966ed39ff8be6ab78cadecf08df3bb02d505/jiter-0.13.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9950290340acc1adaded363edd94baebcee7dabdfa8bee4790794cd5cfad2af6", size = 358551, upload-time = "2026-02-02T12:36:39.417Z" }, + { url = "https://files.pythonhosted.org/packages/a2/ec/a4c72c822695fa80e55d2b4142b73f0012035d9fcf90eccc56bc060db37c/jiter-0.13.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2b4972c6df33731aac0742b64fd0d18e0a69bc7d6e03108ce7d40c85fd9e3e6d", size = 201950, upload-time = "2026-02-02T12:36:40.791Z" }, + { url = "https://files.pythonhosted.org/packages/b6/00/393553ec27b824fbc29047e9c7cd4a3951d7fbe4a76743f17e44034fa4e4/jiter-0.13.0-cp313-cp313t-win_arm64.whl", hash = "sha256:701a1e77d1e593c1b435315ff625fd071f0998c5f02792038a5ca98899261b7d", size = 185852, upload-time = "2026-02-02T12:36:42.077Z" }, { url = "https://files.pythonhosted.org/packages/6e/f5/f1997e987211f6f9bd71b8083047b316208b4aca0b529bb5f8c96c89ef3e/jiter-0.13.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:cc5223ab19fe25e2f0bf2643204ad7318896fe3729bf12fde41b77bfc4fafff0", size = 308804, upload-time = "2026-02-02T12:36:43.496Z" }, { url = "https://files.pythonhosted.org/packages/cd/8f/5482a7677731fd44881f0204981ce2d7175db271f82cba2085dd2212e095/jiter-0.13.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9776ebe51713acf438fd9b4405fcd86893ae5d03487546dae7f34993217f8a91", size = 318787, upload-time = "2026-02-02T12:36:45.071Z" }, { url = "https://files.pythonhosted.org/packages/f3/b9/7257ac59778f1cd025b26a23c5520a36a424f7f1b068f2442a5b499b7464/jiter-0.13.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:879e768938e7b49b5e90b7e3fecc0dbec01b8cb89595861fb39a8967c5220d09", size = 353880, upload-time = "2026-02-02T12:36:47.365Z" }, @@ -783,6 +989,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/47/66/eea81dfff765ed66c68fd2ed8c96245109e13c896c2a5015c7839c92367e/jiter-0.13.0-cp314-cp314t-win32.whl", hash = "sha256:24dc96eca9f84da4131cdf87a95e6ce36765c3b156fc9ae33280873b1c32d5f6", size = 201196, upload-time = "2026-02-02T12:37:19.101Z" }, { url = "https://files.pythonhosted.org/packages/ff/32/4ac9c7a76402f8f00d00842a7f6b83b284d0cf7c1e9d4227bc95aa6d17fa/jiter-0.13.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0a8d76c7524087272c8ae913f5d9d608bd839154b62c4322ef65723d2e5bb0b8", size = 204215, upload-time = "2026-02-02T12:37:20.495Z" }, { url = "https://files.pythonhosted.org/packages/f9/8e/7def204fea9f9be8b3c21a6f2dd6c020cf56c7d5ff753e0e23ed7f9ea57e/jiter-0.13.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2c26cf47e2cad140fa23b6d58d435a7c0161f5c514284802f25e87fddfe11024", size = 187152, upload-time = "2026-02-02T12:37:22.124Z" }, + { url = "https://files.pythonhosted.org/packages/80/60/e50fa45dd7e2eae049f0ce964663849e897300433921198aef94b6ffa23a/jiter-0.13.0-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:3d744a6061afba08dd7ae375dcde870cffb14429b7477e10f67e9e6d68772a0a", size = 305169, upload-time = "2026-02-02T12:37:50.376Z" }, + { url = "https://files.pythonhosted.org/packages/d2/73/a009f41c5eed71c49bec53036c4b33555afcdee70682a18c6f66e396c039/jiter-0.13.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:ff732bd0a0e778f43d5009840f20b935e79087b4dc65bd36f1cd0f9b04b8ff7f", size = 303808, upload-time = "2026-02-02T12:37:52.092Z" }, + { url = "https://files.pythonhosted.org/packages/c4/10/528b439290763bff3d939268085d03382471b442f212dca4ff5f12802d43/jiter-0.13.0-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab44b178f7981fcaea7e0a5df20e773c663d06ffda0198f1a524e91b2fde7e59", size = 337384, upload-time = "2026-02-02T12:37:53.582Z" }, + { url = "https://files.pythonhosted.org/packages/67/8a/a342b2f0251f3dac4ca17618265d93bf244a2a4d089126e81e4c1056ac50/jiter-0.13.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bb00b6d26db67a05fe3e12c76edc75f32077fb51deed13822dc648fa373bc19", size = 343768, upload-time = "2026-02-02T12:37:55.055Z" }, ] [[package]] @@ -882,6 +1092,28 @@ version = "2.6" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/b8/1c/191c3e6ec6502e3dbe25a53e27f69a5daeac3e56de1f73c0138224171ead/lupa-2.6.tar.gz", hash = "sha256:9a770a6e89576be3447668d7ced312cd6fd41d3c13c2462c9dc2c2ab570e45d9", size = 7240282, upload-time = "2025-10-24T07:20:29.738Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/94/86/ce243390535c39d53ea17ccf0240815e6e457e413e40428a658ea4ee4b8d/lupa-2.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:47ce718817ef1cc0c40d87c3d5ae56a800d61af00fbc0fad1ca9be12df2f3b56", size = 951707, upload-time = "2025-10-24T07:18:03.884Z" }, + { url = "https://files.pythonhosted.org/packages/86/85/cedea5e6cbeb54396fdcc55f6b741696f3f036d23cfaf986d50d680446da/lupa-2.6-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:7aba985b15b101495aa4b07112cdc08baa0c545390d560ad5cfde2e9e34f4d58", size = 1916703, upload-time = "2025-10-24T07:18:05.6Z" }, + { url = "https://files.pythonhosted.org/packages/24/be/3d6b5f9a8588c01a4d88129284c726017b2089f3a3fd3ba8bd977292fea0/lupa-2.6-cp312-cp312-macosx_11_0_x86_64.whl", hash = "sha256:b766f62f95b2739f2248977d29b0722e589dcf4f0ccfa827ccbd29f0148bd2e5", size = 985152, upload-time = "2025-10-24T07:18:08.561Z" }, + { url = "https://files.pythonhosted.org/packages/eb/23/9f9a05beee5d5dce9deca4cb07c91c40a90541fc0a8e09db4ee670da550f/lupa-2.6-cp312-cp312-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:00a934c23331f94cb51760097ebfab14b005d55a6b30a2b480e3c53dd2fa290d", size = 1159599, upload-time = "2025-10-24T07:18:10.346Z" }, + { url = "https://files.pythonhosted.org/packages/40/4e/e7c0583083db9d7f1fd023800a9767d8e4391e8330d56c2373d890ac971b/lupa-2.6-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21de9f38bd475303e34a042b7081aabdf50bd9bafd36ce4faea2f90fd9f15c31", size = 1038686, upload-time = "2025-10-24T07:18:12.112Z" }, + { url = "https://files.pythonhosted.org/packages/1c/9f/5a4f7d959d4feba5e203ff0c31889e74d1ca3153122be4a46dca7d92bf7c/lupa-2.6-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cf3bda96d3fc41237e964a69c23647d50d4e28421111360274d4799832c560e9", size = 2071956, upload-time = "2025-10-24T07:18:14.572Z" }, + { url = "https://files.pythonhosted.org/packages/92/34/2f4f13ca65d01169b1720176aedc4af17bc19ee834598c7292db232cb6dc/lupa-2.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5a76ead245da54801a81053794aa3975f213221f6542d14ec4b859ee2e7e0323", size = 1057199, upload-time = "2025-10-24T07:18:16.379Z" }, + { url = "https://files.pythonhosted.org/packages/35/2a/5f7d2eebec6993b0dcd428e0184ad71afb06a45ba13e717f6501bfed1da3/lupa-2.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8dd0861741caa20886ddbda0a121d8e52fb9b5bb153d82fa9bba796962bf30e8", size = 1173693, upload-time = "2025-10-24T07:18:18.153Z" }, + { url = "https://files.pythonhosted.org/packages/e4/29/089b4d2f8e34417349af3904bb40bec40b65c8731f45e3fd8d497ca573e5/lupa-2.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:239e63948b0b23023f81d9a19a395e768ed3da6a299f84e7963b8f813f6e3f9c", size = 2164394, upload-time = "2025-10-24T07:18:20.403Z" }, + { url = "https://files.pythonhosted.org/packages/f3/1b/79c17b23c921f81468a111cad843b076a17ef4b684c4a8dff32a7969c3f0/lupa-2.6-cp312-cp312-win32.whl", hash = "sha256:325894e1099499e7a6f9c351147661a2011887603c71086d36fe0f964d52d1ce", size = 1420647, upload-time = "2025-10-24T07:18:23.368Z" }, + { url = "https://files.pythonhosted.org/packages/b8/15/5121e68aad3584e26e1425a5c9a79cd898f8a152292059e128c206ee817c/lupa-2.6-cp312-cp312-win_amd64.whl", hash = "sha256:c735a1ce8ee60edb0fe71d665f1e6b7c55c6021f1d340eb8c865952c602cd36f", size = 1688529, upload-time = "2025-10-24T07:18:25.523Z" }, + { url = "https://files.pythonhosted.org/packages/28/1d/21176b682ca5469001199d8b95fa1737e29957a3d185186e7a8b55345f2e/lupa-2.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:663a6e58a0f60e7d212017d6678639ac8df0119bc13c2145029dcba084391310", size = 947232, upload-time = "2025-10-24T07:18:27.878Z" }, + { url = "https://files.pythonhosted.org/packages/ce/4c/d327befb684660ca13cf79cd1f1d604331808f9f1b6fb6bf57832f8edf80/lupa-2.6-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:d1f5afda5c20b1f3217a80e9bc1b77037f8a6eb11612fd3ada19065303c8f380", size = 1908625, upload-time = "2025-10-24T07:18:29.944Z" }, + { url = "https://files.pythonhosted.org/packages/66/8e/ad22b0a19454dfd08662237a84c792d6d420d36b061f239e084f29d1a4f3/lupa-2.6-cp313-cp313-macosx_11_0_x86_64.whl", hash = "sha256:26f2b3c085fe76e9119e48c1013c1cccdc1f51585d456858290475aa38e7089e", size = 981057, upload-time = "2025-10-24T07:18:31.553Z" }, + { url = "https://files.pythonhosted.org/packages/5c/48/74859073ab276bd0566c719f9ca0108b0cfc1956ca0d68678d117d47d155/lupa-2.6-cp313-cp313-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:60d2f902c7b96fb8ab98493dcff315e7bb4d0b44dc9dd76eb37de575025d5685", size = 1156227, upload-time = "2025-10-24T07:18:33.981Z" }, + { url = "https://files.pythonhosted.org/packages/09/6c/0e9ded061916877253c2266074060eb71ed99fb21d73c8c114a76725bce2/lupa-2.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a02d25dee3a3250967c36590128d9220ae02f2eda166a24279da0b481519cbff", size = 1035752, upload-time = "2025-10-24T07:18:36.32Z" }, + { url = "https://files.pythonhosted.org/packages/dd/ef/f8c32e454ef9f3fe909f6c7d57a39f950996c37a3deb7b391fec7903dab7/lupa-2.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6eae1ee16b886b8914ff292dbefbf2f48abfbdee94b33a88d1d5475e02423203", size = 2069009, upload-time = "2025-10-24T07:18:38.072Z" }, + { url = "https://files.pythonhosted.org/packages/53/dc/15b80c226a5225815a890ee1c11f07968e0aba7a852df41e8ae6fe285063/lupa-2.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0edd5073a4ee74ab36f74fe61450148e6044f3952b8d21248581f3c5d1a58be", size = 1056301, upload-time = "2025-10-24T07:18:40.165Z" }, + { url = "https://files.pythonhosted.org/packages/31/14/2086c1425c985acfb30997a67e90c39457122df41324d3c179d6ee2292c6/lupa-2.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:0c53ee9f22a8a17e7d4266ad48e86f43771951797042dd51d1494aaa4f5f3f0a", size = 1170673, upload-time = "2025-10-24T07:18:42.426Z" }, + { url = "https://files.pythonhosted.org/packages/10/e5/b216c054cf86576c0191bf9a9f05de6f7e8e07164897d95eea0078dca9b2/lupa-2.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:de7c0f157a9064a400d828789191a96da7f4ce889969a588b87ec80de9b14772", size = 2162227, upload-time = "2025-10-24T07:18:46.112Z" }, + { url = "https://files.pythonhosted.org/packages/59/2f/33ecb5bedf4f3bc297ceacb7f016ff951331d352f58e7e791589609ea306/lupa-2.6-cp313-cp313-win32.whl", hash = "sha256:ee9523941ae0a87b5b703417720c5d78f72d2f5bc23883a2ea80a949a3ed9e75", size = 1419558, upload-time = "2025-10-24T07:18:48.371Z" }, + { url = "https://files.pythonhosted.org/packages/f9/b4/55e885834c847ea610e111d87b9ed4768f0afdaeebc00cd46810f25029f6/lupa-2.6-cp313-cp313-win_amd64.whl", hash = "sha256:b1335a5835b0a25ebdbc75cf0bda195e54d133e4d994877ef025e218c2e59db9", size = 1683424, upload-time = "2025-10-24T07:18:50.976Z" }, { url = "https://files.pythonhosted.org/packages/66/9d/d9427394e54d22a35d1139ef12e845fd700d4872a67a34db32516170b746/lupa-2.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:dcb6d0a3264873e1653bc188499f48c1fb4b41a779e315eba45256cfe7bc33c1", size = 953818, upload-time = "2025-10-24T07:18:53.378Z" }, { url = "https://files.pythonhosted.org/packages/10/41/27bbe81953fb2f9ecfced5d9c99f85b37964cfaf6aa8453bb11283983721/lupa-2.6-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:a37e01f2128f8c36106726cb9d360bac087d58c54b4522b033cc5691c584db18", size = 1915850, upload-time = "2025-10-24T07:18:55.259Z" }, { url = "https://files.pythonhosted.org/packages/a3/98/f9ff60db84a75ba8725506bbf448fb085bc77868a021998ed2a66d920568/lupa-2.6-cp314-cp314-macosx_11_0_x86_64.whl", hash = "sha256:458bd7e9ff3c150b245b0fcfbb9bd2593d1152ea7f0a7b91c1d185846da033fe", size = 982344, upload-time = "2025-10-24T07:18:57.05Z" }, @@ -924,6 +1156,39 @@ version = "3.0.3" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615, upload-time = "2025-09-27T18:36:30.854Z" }, + { url = "https://files.pythonhosted.org/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020, upload-time = "2025-09-27T18:36:31.971Z" }, + { url = "https://files.pythonhosted.org/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332, upload-time = "2025-09-27T18:36:32.813Z" }, + { url = "https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947, upload-time = "2025-09-27T18:36:33.86Z" }, + { url = "https://files.pythonhosted.org/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962, upload-time = "2025-09-27T18:36:35.099Z" }, + { url = "https://files.pythonhosted.org/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760, upload-time = "2025-09-27T18:36:36.001Z" }, + { url = "https://files.pythonhosted.org/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529, upload-time = "2025-09-27T18:36:36.906Z" }, + { url = "https://files.pythonhosted.org/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015, upload-time = "2025-09-27T18:36:37.868Z" }, + { url = "https://files.pythonhosted.org/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540, upload-time = "2025-09-27T18:36:38.761Z" }, + { url = "https://files.pythonhosted.org/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105, upload-time = "2025-09-27T18:36:39.701Z" }, + { url = "https://files.pythonhosted.org/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906, upload-time = "2025-09-27T18:36:40.689Z" }, + { url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" }, + { url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" }, + { url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" }, + { url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" }, + { url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" }, + { url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" }, + { url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" }, + { url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" }, + { url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" }, + { url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" }, + { url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" }, + { url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" }, + { url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" }, + { url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" }, + { url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" }, + { url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" }, + { url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" }, + { url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" }, + { url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" }, + { url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" }, { url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" }, { url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" }, { url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" }, @@ -1003,6 +1268,60 @@ version = "6.7.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/1a/c2/c2d94cbe6ac1753f3fc980da97b3d930efe1da3af3c9f5125354436c073d/multidict-6.7.1.tar.gz", hash = "sha256:ec6652a1bee61c53a3e5776b6049172c53b6aaba34f18c9ad04f82712bac623d", size = 102010, upload-time = "2026-01-26T02:46:45.979Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/9c/f20e0e2cf80e4b2e4b1c365bf5fe104ee633c751a724246262db8f1a0b13/multidict-6.7.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:a90f75c956e32891a4eda3639ce6dd86e87105271f43d43442a3aedf3cddf172", size = 76893, upload-time = "2026-01-26T02:43:52.754Z" }, + { url = "https://files.pythonhosted.org/packages/fe/cf/18ef143a81610136d3da8193da9d80bfe1cb548a1e2d1c775f26b23d024a/multidict-6.7.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fccb473e87eaa1382689053e4a4618e7ba7b9b9b8d6adf2027ee474597128cd", size = 45456, upload-time = "2026-01-26T02:43:53.893Z" }, + { url = "https://files.pythonhosted.org/packages/a9/65/1caac9d4cd32e8433908683446eebc953e82d22b03d10d41a5f0fefe991b/multidict-6.7.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b0fa96985700739c4c7853a43c0b3e169360d6855780021bfc6d0f1ce7c123e7", size = 43872, upload-time = "2026-01-26T02:43:55.041Z" }, + { url = "https://files.pythonhosted.org/packages/cf/3b/d6bd75dc4f3ff7c73766e04e705b00ed6dbbaccf670d9e05a12b006f5a21/multidict-6.7.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cb2a55f408c3043e42b40cc8eecd575afa27b7e0b956dfb190de0f8499a57a53", size = 251018, upload-time = "2026-01-26T02:43:56.198Z" }, + { url = "https://files.pythonhosted.org/packages/fd/80/c959c5933adedb9ac15152e4067c702a808ea183a8b64cf8f31af8ad3155/multidict-6.7.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eb0ce7b2a32d09892b3dd6cc44877a0d02a33241fafca5f25c8b6b62374f8b75", size = 258883, upload-time = "2026-01-26T02:43:57.499Z" }, + { url = "https://files.pythonhosted.org/packages/86/85/7ed40adafea3d4f1c8b916e3b5cc3a8e07dfcdcb9cd72800f4ed3ca1b387/multidict-6.7.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c3a32d23520ee37bf327d1e1a656fec76a2edd5c038bf43eddfa0572ec49c60b", size = 242413, upload-time = "2026-01-26T02:43:58.755Z" }, + { url = "https://files.pythonhosted.org/packages/d2/57/b8565ff533e48595503c785f8361ff9a4fde4d67de25c207cd0ba3befd03/multidict-6.7.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9c90fed18bffc0189ba814749fdcc102b536e83a9f738a9003e569acd540a733", size = 268404, upload-time = "2026-01-26T02:44:00.216Z" }, + { url = "https://files.pythonhosted.org/packages/e0/50/9810c5c29350f7258180dfdcb2e52783a0632862eb334c4896ac717cebcb/multidict-6.7.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:da62917e6076f512daccfbbde27f46fed1c98fee202f0559adec8ee0de67f71a", size = 269456, upload-time = "2026-01-26T02:44:02.202Z" }, + { url = "https://files.pythonhosted.org/packages/f3/8d/5e5be3ced1d12966fefb5c4ea3b2a5b480afcea36406559442c6e31d4a48/multidict-6.7.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bfde23ef6ed9db7eaee6c37dcec08524cb43903c60b285b172b6c094711b3961", size = 256322, upload-time = "2026-01-26T02:44:03.56Z" }, + { url = "https://files.pythonhosted.org/packages/31/6e/d8a26d81ac166a5592782d208dd90dfdc0a7a218adaa52b45a672b46c122/multidict-6.7.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3758692429e4e32f1ba0df23219cd0b4fc0a52f476726fff9337d1a57676a582", size = 253955, upload-time = "2026-01-26T02:44:04.845Z" }, + { url = "https://files.pythonhosted.org/packages/59/4c/7c672c8aad41534ba619bcd4ade7a0dc87ed6b8b5c06149b85d3dd03f0cd/multidict-6.7.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:398c1478926eca669f2fd6a5856b6de9c0acf23a2cb59a14c0ba5844fa38077e", size = 251254, upload-time = "2026-01-26T02:44:06.133Z" }, + { url = "https://files.pythonhosted.org/packages/7b/bd/84c24de512cbafbdbc39439f74e967f19570ce7924e3007174a29c348916/multidict-6.7.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c102791b1c4f3ab36ce4101154549105a53dc828f016356b3e3bcae2e3a039d3", size = 252059, upload-time = "2026-01-26T02:44:07.518Z" }, + { url = "https://files.pythonhosted.org/packages/fa/ba/f5449385510825b73d01c2d4087bf6d2fccc20a2d42ac34df93191d3dd03/multidict-6.7.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:a088b62bd733e2ad12c50dad01b7d0166c30287c166e137433d3b410add807a6", size = 263588, upload-time = "2026-01-26T02:44:09.382Z" }, + { url = "https://files.pythonhosted.org/packages/d7/11/afc7c677f68f75c84a69fe37184f0f82fce13ce4b92f49f3db280b7e92b3/multidict-6.7.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3d51ff4785d58d3f6c91bdbffcb5e1f7ddfda557727043aa20d20ec4f65e324a", size = 259642, upload-time = "2026-01-26T02:44:10.73Z" }, + { url = "https://files.pythonhosted.org/packages/2b/17/ebb9644da78c4ab36403739e0e6e0e30ebb135b9caf3440825001a0bddcb/multidict-6.7.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc5907494fccf3e7d3f94f95c91d6336b092b5fc83811720fae5e2765890dfba", size = 251377, upload-time = "2026-01-26T02:44:12.042Z" }, + { url = "https://files.pythonhosted.org/packages/ca/a4/840f5b97339e27846c46307f2530a2805d9d537d8b8bd416af031cad7fa0/multidict-6.7.1-cp312-cp312-win32.whl", hash = "sha256:28ca5ce2fd9716631133d0e9a9b9a745ad7f60bac2bccafb56aa380fc0b6c511", size = 41887, upload-time = "2026-01-26T02:44:14.245Z" }, + { url = "https://files.pythonhosted.org/packages/80/31/0b2517913687895f5904325c2069d6a3b78f66cc641a86a2baf75a05dcbb/multidict-6.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcee94dfbd638784645b066074b338bc9cc155d4b4bffa4adce1615c5a426c19", size = 46053, upload-time = "2026-01-26T02:44:15.371Z" }, + { url = "https://files.pythonhosted.org/packages/0c/5b/aba28e4ee4006ae4c7df8d327d31025d760ffa992ea23812a601d226e682/multidict-6.7.1-cp312-cp312-win_arm64.whl", hash = "sha256:ba0a9fb644d0c1a2194cf7ffb043bd852cea63a57f66fbd33959f7dae18517bf", size = 43307, upload-time = "2026-01-26T02:44:16.852Z" }, + { url = "https://files.pythonhosted.org/packages/f2/22/929c141d6c0dba87d3e1d38fbdf1ba8baba86b7776469f2bc2d3227a1e67/multidict-6.7.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2b41f5fed0ed563624f1c17630cb9941cf2309d4df00e494b551b5f3e3d67a23", size = 76174, upload-time = "2026-01-26T02:44:18.509Z" }, + { url = "https://files.pythonhosted.org/packages/c7/75/bc704ae15fee974f8fccd871305e254754167dce5f9e42d88a2def741a1d/multidict-6.7.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84e61e3af5463c19b67ced91f6c634effb89ef8bfc5ca0267f954451ed4bb6a2", size = 45116, upload-time = "2026-01-26T02:44:19.745Z" }, + { url = "https://files.pythonhosted.org/packages/79/76/55cd7186f498ed080a18440c9013011eb548f77ae1b297206d030eb1180a/multidict-6.7.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:935434b9853c7c112eee7ac891bc4cb86455aa631269ae35442cb316790c1445", size = 43524, upload-time = "2026-01-26T02:44:21.571Z" }, + { url = "https://files.pythonhosted.org/packages/e9/3c/414842ef8d5a1628d68edee29ba0e5bcf235dbfb3ccd3ea303a7fe8c72ff/multidict-6.7.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:432feb25a1cb67fe82a9680b4d65fb542e4635cb3166cd9c01560651ad60f177", size = 249368, upload-time = "2026-01-26T02:44:22.803Z" }, + { url = "https://files.pythonhosted.org/packages/f6/32/befed7f74c458b4a525e60519fe8d87eef72bb1e99924fa2b0f9d97a221e/multidict-6.7.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e82d14e3c948952a1a85503817e038cba5905a3352de76b9a465075d072fba23", size = 256952, upload-time = "2026-01-26T02:44:24.306Z" }, + { url = "https://files.pythonhosted.org/packages/03/d6/c878a44ba877f366630c860fdf74bfb203c33778f12b6ac274936853c451/multidict-6.7.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4cfb48c6ea66c83bcaaf7e4dfa7ec1b6bbcf751b7db85a328902796dfde4c060", size = 240317, upload-time = "2026-01-26T02:44:25.772Z" }, + { url = "https://files.pythonhosted.org/packages/68/49/57421b4d7ad2e9e60e25922b08ceb37e077b90444bde6ead629095327a6f/multidict-6.7.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1d540e51b7e8e170174555edecddbd5538105443754539193e3e1061864d444d", size = 267132, upload-time = "2026-01-26T02:44:27.648Z" }, + { url = "https://files.pythonhosted.org/packages/b7/fe/ec0edd52ddbcea2a2e89e174f0206444a61440b40f39704e64dc807a70bd/multidict-6.7.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:273d23f4b40f3dce4d6c8a821c741a86dec62cded82e1175ba3d99be128147ed", size = 268140, upload-time = "2026-01-26T02:44:29.588Z" }, + { url = "https://files.pythonhosted.org/packages/b0/73/6e1b01cbeb458807aa0831742232dbdd1fa92bfa33f52a3f176b4ff3dc11/multidict-6.7.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d624335fd4fa1c08a53f8b4be7676ebde19cd092b3895c421045ca87895b429", size = 254277, upload-time = "2026-01-26T02:44:30.902Z" }, + { url = "https://files.pythonhosted.org/packages/6a/b2/5fb8c124d7561a4974c342bc8c778b471ebbeb3cc17df696f034a7e9afe7/multidict-6.7.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:12fad252f8b267cc75b66e8fc51b3079604e8d43a75428ffe193cd9e2195dfd6", size = 252291, upload-time = "2026-01-26T02:44:32.31Z" }, + { url = "https://files.pythonhosted.org/packages/5a/96/51d4e4e06bcce92577fcd488e22600bd38e4fd59c20cb49434d054903bd2/multidict-6.7.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:03ede2a6ffbe8ef936b92cb4529f27f42be7f56afcdab5ab739cd5f27fb1cbf9", size = 250156, upload-time = "2026-01-26T02:44:33.734Z" }, + { url = "https://files.pythonhosted.org/packages/db/6b/420e173eec5fba721a50e2a9f89eda89d9c98fded1124f8d5c675f7a0c0f/multidict-6.7.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:90efbcf47dbe33dcf643a1e400d67d59abeac5db07dc3f27d6bdeae497a2198c", size = 249742, upload-time = "2026-01-26T02:44:35.222Z" }, + { url = "https://files.pythonhosted.org/packages/44/a3/ec5b5bd98f306bc2aa297b8c6f11a46714a56b1e6ef5ebda50a4f5d7c5fb/multidict-6.7.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5c4b9bfc148f5a91be9244d6264c53035c8a0dcd2f51f1c3c6e30e30ebaa1c84", size = 262221, upload-time = "2026-01-26T02:44:36.604Z" }, + { url = "https://files.pythonhosted.org/packages/cd/f7/e8c0d0da0cd1e28d10e624604e1a36bcc3353aaebdfdc3a43c72bc683a12/multidict-6.7.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:401c5a650f3add2472d1d288c26deebc540f99e2fb83e9525007a74cd2116f1d", size = 258664, upload-time = "2026-01-26T02:44:38.008Z" }, + { url = "https://files.pythonhosted.org/packages/52/da/151a44e8016dd33feed44f730bd856a66257c1ee7aed4f44b649fb7edeb3/multidict-6.7.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:97891f3b1b3ffbded884e2916cacf3c6fc87b66bb0dde46f7357404750559f33", size = 249490, upload-time = "2026-01-26T02:44:39.386Z" }, + { url = "https://files.pythonhosted.org/packages/87/af/a3b86bf9630b732897f6fc3f4c4714b90aa4361983ccbdcd6c0339b21b0c/multidict-6.7.1-cp313-cp313-win32.whl", hash = "sha256:e1c5988359516095535c4301af38d8a8838534158f649c05dd1050222321bcb3", size = 41695, upload-time = "2026-01-26T02:44:41.318Z" }, + { url = "https://files.pythonhosted.org/packages/b2/35/e994121b0e90e46134673422dd564623f93304614f5d11886b1b3e06f503/multidict-6.7.1-cp313-cp313-win_amd64.whl", hash = "sha256:960c83bf01a95b12b08fd54324a4eb1d5b52c88932b5cba5d6e712bb3ed12eb5", size = 45884, upload-time = "2026-01-26T02:44:42.488Z" }, + { url = "https://files.pythonhosted.org/packages/ca/61/42d3e5dbf661242a69c97ea363f2d7b46c567da8eadef8890022be6e2ab0/multidict-6.7.1-cp313-cp313-win_arm64.whl", hash = "sha256:563fe25c678aaba333d5399408f5ec3c383ca5b663e7f774dd179a520b8144df", size = 43122, upload-time = "2026-01-26T02:44:43.664Z" }, + { url = "https://files.pythonhosted.org/packages/6d/b3/e6b21c6c4f314bb956016b0b3ef2162590a529b84cb831c257519e7fde44/multidict-6.7.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:c76c4bec1538375dad9d452d246ca5368ad6e1c9039dadcf007ae59c70619ea1", size = 83175, upload-time = "2026-01-26T02:44:44.894Z" }, + { url = "https://files.pythonhosted.org/packages/fb/76/23ecd2abfe0957b234f6c960f4ade497f55f2c16aeb684d4ecdbf1c95791/multidict-6.7.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:57b46b24b5d5ebcc978da4ec23a819a9402b4228b8a90d9c656422b4bdd8a963", size = 48460, upload-time = "2026-01-26T02:44:46.106Z" }, + { url = "https://files.pythonhosted.org/packages/c4/57/a0ed92b23f3a042c36bc4227b72b97eca803f5f1801c1ab77c8a212d455e/multidict-6.7.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e954b24433c768ce78ab7929e84ccf3422e46deb45a4dc9f93438f8217fa2d34", size = 46930, upload-time = "2026-01-26T02:44:47.278Z" }, + { url = "https://files.pythonhosted.org/packages/b5/66/02ec7ace29162e447f6382c495dc95826bf931d3818799bbef11e8f7df1a/multidict-6.7.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3bd231490fa7217cc832528e1cd8752a96f0125ddd2b5749390f7c3ec8721b65", size = 242582, upload-time = "2026-01-26T02:44:48.604Z" }, + { url = "https://files.pythonhosted.org/packages/58/18/64f5a795e7677670e872673aca234162514696274597b3708b2c0d276cce/multidict-6.7.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:253282d70d67885a15c8a7716f3a73edf2d635793ceda8173b9ecc21f2fb8292", size = 250031, upload-time = "2026-01-26T02:44:50.544Z" }, + { url = "https://files.pythonhosted.org/packages/c8/ed/e192291dbbe51a8290c5686f482084d31bcd9d09af24f63358c3d42fd284/multidict-6.7.1-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0b4c48648d7649c9335cf1927a8b87fa692de3dcb15faa676c6a6f1f1aabda43", size = 228596, upload-time = "2026-01-26T02:44:51.951Z" }, + { url = "https://files.pythonhosted.org/packages/1e/7e/3562a15a60cf747397e7f2180b0a11dc0c38d9175a650e75fa1b4d325e15/multidict-6.7.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:98bc624954ec4d2c7cb074b8eefc2b5d0ce7d482e410df446414355d158fe4ca", size = 257492, upload-time = "2026-01-26T02:44:53.902Z" }, + { url = "https://files.pythonhosted.org/packages/24/02/7d0f9eae92b5249bb50ac1595b295f10e263dd0078ebb55115c31e0eaccd/multidict-6.7.1-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1b99af4d9eec0b49927b4402bcbb58dea89d3e0db8806a4086117019939ad3dd", size = 255899, upload-time = "2026-01-26T02:44:55.316Z" }, + { url = "https://files.pythonhosted.org/packages/00/e3/9b60ed9e23e64c73a5cde95269ef1330678e9c6e34dd4eb6b431b85b5a10/multidict-6.7.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6aac4f16b472d5b7dc6f66a0d49dd57b0e0902090be16594dc9ebfd3d17c47e7", size = 247970, upload-time = "2026-01-26T02:44:56.783Z" }, + { url = "https://files.pythonhosted.org/packages/3e/06/538e58a63ed5cfb0bd4517e346b91da32fde409d839720f664e9a4ae4f9d/multidict-6.7.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:21f830fe223215dffd51f538e78c172ed7c7f60c9b96a2bf05c4848ad49921c3", size = 245060, upload-time = "2026-01-26T02:44:58.195Z" }, + { url = "https://files.pythonhosted.org/packages/b2/2f/d743a3045a97c895d401e9bd29aaa09b94f5cbdf1bd561609e5a6c431c70/multidict-6.7.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f5dd81c45b05518b9aa4da4aa74e1c93d715efa234fd3e8a179df611cc85e5f4", size = 235888, upload-time = "2026-01-26T02:44:59.57Z" }, + { url = "https://files.pythonhosted.org/packages/38/83/5a325cac191ab28b63c52f14f1131f3b0a55ba3b9aa65a6d0bf2a9b921a0/multidict-6.7.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:eb304767bca2bb92fb9c5bd33cedc95baee5bb5f6c88e63706533a1c06ad08c8", size = 243554, upload-time = "2026-01-26T02:45:01.054Z" }, + { url = "https://files.pythonhosted.org/packages/20/1f/9d2327086bd15da2725ef6aae624208e2ef828ed99892b17f60c344e57ed/multidict-6.7.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:c9035dde0f916702850ef66460bc4239d89d08df4d02023a5926e7446724212c", size = 252341, upload-time = "2026-01-26T02:45:02.484Z" }, + { url = "https://files.pythonhosted.org/packages/e8/2c/2a1aa0280cf579d0f6eed8ee5211c4f1730bd7e06c636ba2ee6aafda302e/multidict-6.7.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:af959b9beeb66c822380f222f0e0a1889331597e81f1ded7f374f3ecb0fd6c52", size = 246391, upload-time = "2026-01-26T02:45:03.862Z" }, + { url = "https://files.pythonhosted.org/packages/e5/03/7ca022ffc36c5a3f6e03b179a5ceb829be9da5783e6fe395f347c0794680/multidict-6.7.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:41f2952231456154ee479651491e94118229844dd7226541788be783be2b5108", size = 243422, upload-time = "2026-01-26T02:45:05.296Z" }, + { url = "https://files.pythonhosted.org/packages/dc/1d/b31650eab6c5778aceed46ba735bd97f7c7d2f54b319fa916c0f96e7805b/multidict-6.7.1-cp313-cp313t-win32.whl", hash = "sha256:df9f19c28adcb40b6aae30bbaa1478c389efd50c28d541d76760199fc1037c32", size = 47770, upload-time = "2026-01-26T02:45:06.754Z" }, + { url = "https://files.pythonhosted.org/packages/ac/5b/2d2d1d522e51285bd61b1e20df8f47ae1a9d80839db0b24ea783b3832832/multidict-6.7.1-cp313-cp313t-win_amd64.whl", hash = "sha256:d54ecf9f301853f2c5e802da559604b3e95bb7a3b01a9c295c6ee591b9882de8", size = 53109, upload-time = "2026-01-26T02:45:08.044Z" }, + { url = "https://files.pythonhosted.org/packages/3d/a3/cc409ba012c83ca024a308516703cf339bdc4b696195644a7215a5164a24/multidict-6.7.1-cp313-cp313t-win_arm64.whl", hash = "sha256:5a37ca18e360377cfda1d62f5f382ff41f2b8c4ccb329ed974cc2e1643440118", size = 45573, upload-time = "2026-01-26T02:45:09.349Z" }, { url = "https://files.pythonhosted.org/packages/91/cc/db74228a8be41884a567e88a62fd589a913708fcf180d029898c17a9a371/multidict-6.7.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8f333ec9c5eb1b7105e3b84b53141e66ca05a19a605368c55450b6ba208cb9ee", size = 75190, upload-time = "2026-01-26T02:45:10.651Z" }, { url = "https://files.pythonhosted.org/packages/d5/22/492f2246bb5b534abd44804292e81eeaf835388901f0c574bac4eeec73c5/multidict-6.7.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:a407f13c188f804c759fc6a9f88286a565c242a76b27626594c133b82883b5c2", size = 44486, upload-time = "2026-01-26T02:45:11.938Z" }, { url = "https://files.pythonhosted.org/packages/f1/4f/733c48f270565d78b4544f2baddc2fb2a245e5a8640254b12c36ac7ac68e/multidict-6.7.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0e161ddf326db5577c3a4cc2d8648f81456e8a20d40415541587a71620d7a7d1", size = 43219, upload-time = "2026-01-26T02:45:14.346Z" }, @@ -1048,6 +1367,38 @@ version = "2.4.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/57/fd/0005efbd0af48e55eb3c7208af93f2862d4b1a56cd78e84309a2d959208d/numpy-2.4.2.tar.gz", hash = "sha256:659a6107e31a83c4e33f763942275fd278b21d095094044eb35569e86a21ddae", size = 20723651, upload-time = "2026-01-31T23:13:10.135Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/51/6e/6f394c9c77668153e14d4da83bcc247beb5952f6ead7699a1a2992613bea/numpy-2.4.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:21982668592194c609de53ba4933a7471880ccbaadcc52352694a59ecc860b3a", size = 16667963, upload-time = "2026-01-31T23:10:52.147Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f8/55483431f2b2fd015ae6ed4fe62288823ce908437ed49db5a03d15151678/numpy-2.4.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40397bda92382fcec844066efb11f13e1c9a3e2a8e8f318fb72ed8b6db9f60f1", size = 14693571, upload-time = "2026-01-31T23:10:54.789Z" }, + { url = "https://files.pythonhosted.org/packages/2f/20/18026832b1845cdc82248208dd929ca14c9d8f2bac391f67440707fff27c/numpy-2.4.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:b3a24467af63c67829bfaa61eecf18d5432d4f11992688537be59ecd6ad32f5e", size = 5203469, upload-time = "2026-01-31T23:10:57.343Z" }, + { url = "https://files.pythonhosted.org/packages/7d/33/2eb97c8a77daaba34eaa3fa7241a14ac5f51c46a6bd5911361b644c4a1e2/numpy-2.4.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:805cc8de9fd6e7a22da5aed858e0ab16be5a4db6c873dde1d7451c541553aa27", size = 6550820, upload-time = "2026-01-31T23:10:59.429Z" }, + { url = "https://files.pythonhosted.org/packages/b1/91/b97fdfd12dc75b02c44e26c6638241cc004d4079a0321a69c62f51470c4c/numpy-2.4.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d82351358ffbcdcd7b686b90742a9b86632d6c1c051016484fa0b326a0a1548", size = 15663067, upload-time = "2026-01-31T23:11:01.291Z" }, + { url = "https://files.pythonhosted.org/packages/f5/c6/a18e59f3f0b8071cc85cbc8d80cd02d68aa9710170b2553a117203d46936/numpy-2.4.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e35d3e0144137d9fdae62912e869136164534d64a169f86438bc9561b6ad49f", size = 16619782, upload-time = "2026-01-31T23:11:03.669Z" }, + { url = "https://files.pythonhosted.org/packages/b7/83/9751502164601a79e18847309f5ceec0b1446d7b6aa12305759b72cf98b2/numpy-2.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:adb6ed2ad29b9e15321d167d152ee909ec73395901b70936f029c3bc6d7f4460", size = 17013128, upload-time = "2026-01-31T23:11:05.913Z" }, + { url = "https://files.pythonhosted.org/packages/61/c4/c4066322256ec740acc1c8923a10047818691d2f8aec254798f3dd90f5f2/numpy-2.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8906e71fd8afcb76580404e2a950caef2685df3d2a57fe82a86ac8d33cc007ba", size = 18345324, upload-time = "2026-01-31T23:11:08.248Z" }, + { url = "https://files.pythonhosted.org/packages/ab/af/6157aa6da728fa4525a755bfad486ae7e3f76d4c1864138003eb84328497/numpy-2.4.2-cp312-cp312-win32.whl", hash = "sha256:ec055f6dae239a6299cace477b479cca2fc125c5675482daf1dd886933a1076f", size = 5960282, upload-time = "2026-01-31T23:11:10.497Z" }, + { url = "https://files.pythonhosted.org/packages/92/0f/7ceaaeaacb40567071e94dbf2c9480c0ae453d5bb4f52bea3892c39dc83c/numpy-2.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:209fae046e62d0ce6435fcfe3b1a10537e858249b3d9b05829e2a05218296a85", size = 12314210, upload-time = "2026-01-31T23:11:12.176Z" }, + { url = "https://files.pythonhosted.org/packages/2f/a3/56c5c604fae6dd40fa2ed3040d005fca97e91bd320d232ac9931d77ba13c/numpy-2.4.2-cp312-cp312-win_arm64.whl", hash = "sha256:fbde1b0c6e81d56f5dccd95dd4a711d9b95df1ae4009a60887e56b27e8d903fa", size = 10220171, upload-time = "2026-01-31T23:11:14.684Z" }, + { url = "https://files.pythonhosted.org/packages/a1/22/815b9fe25d1d7ae7d492152adbc7226d3eff731dffc38fe970589fcaaa38/numpy-2.4.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:25f2059807faea4b077a2b6837391b5d830864b3543627f381821c646f31a63c", size = 16663696, upload-time = "2026-01-31T23:11:17.516Z" }, + { url = "https://files.pythonhosted.org/packages/09/f0/817d03a03f93ba9c6c8993de509277d84e69f9453601915e4a69554102a1/numpy-2.4.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bd3a7a9f5847d2fb8c2c6d1c862fa109c31a9abeca1a3c2bd5a64572955b2979", size = 14688322, upload-time = "2026-01-31T23:11:19.883Z" }, + { url = "https://files.pythonhosted.org/packages/da/b4/f805ab79293c728b9a99438775ce51885fd4f31b76178767cfc718701a39/numpy-2.4.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:8e4549f8a3c6d13d55041925e912bfd834285ef1dd64d6bc7d542583355e2e98", size = 5198157, upload-time = "2026-01-31T23:11:22.375Z" }, + { url = "https://files.pythonhosted.org/packages/74/09/826e4289844eccdcd64aac27d13b0fd3f32039915dd5b9ba01baae1f436c/numpy-2.4.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:aea4f66ff44dfddf8c2cffd66ba6538c5ec67d389285292fe428cb2c738c8aef", size = 6546330, upload-time = "2026-01-31T23:11:23.958Z" }, + { url = "https://files.pythonhosted.org/packages/19/fb/cbfdbfa3057a10aea5422c558ac57538e6acc87ec1669e666d32ac198da7/numpy-2.4.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c3cd545784805de05aafe1dde61752ea49a359ccba9760c1e5d1c88a93bbf2b7", size = 15660968, upload-time = "2026-01-31T23:11:25.713Z" }, + { url = "https://files.pythonhosted.org/packages/04/dc/46066ce18d01645541f0186877377b9371b8fa8017fa8262002b4ef22612/numpy-2.4.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d0d9b7c93578baafcbc5f0b83eaf17b79d345c6f36917ba0c67f45226911d499", size = 16607311, upload-time = "2026-01-31T23:11:28.117Z" }, + { url = "https://files.pythonhosted.org/packages/14/d9/4b5adfc39a43fa6bf918c6d544bc60c05236cc2f6339847fc5b35e6cb5b0/numpy-2.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f74f0f7779cc7ae07d1810aab8ac6b1464c3eafb9e283a40da7309d5e6e48fbb", size = 17012850, upload-time = "2026-01-31T23:11:30.888Z" }, + { url = "https://files.pythonhosted.org/packages/b7/20/adb6e6adde6d0130046e6fdfb7675cc62bc2f6b7b02239a09eb58435753d/numpy-2.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c7ac672d699bf36275c035e16b65539931347d68b70667d28984c9fb34e07fa7", size = 18334210, upload-time = "2026-01-31T23:11:33.214Z" }, + { url = "https://files.pythonhosted.org/packages/78/0e/0a73b3dff26803a8c02baa76398015ea2a5434d9b8265a7898a6028c1591/numpy-2.4.2-cp313-cp313-win32.whl", hash = "sha256:8e9afaeb0beff068b4d9cd20d322ba0ee1cecfb0b08db145e4ab4dd44a6b5110", size = 5958199, upload-time = "2026-01-31T23:11:35.385Z" }, + { url = "https://files.pythonhosted.org/packages/43/bc/6352f343522fcb2c04dbaf94cb30cca6fd32c1a750c06ad6231b4293708c/numpy-2.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:7df2de1e4fba69a51c06c28f5a3de36731eb9639feb8e1cf7e4a7b0daf4cf622", size = 12310848, upload-time = "2026-01-31T23:11:38.001Z" }, + { url = "https://files.pythonhosted.org/packages/6e/8d/6da186483e308da5da1cc6918ce913dcfe14ffde98e710bfeff2a6158d4e/numpy-2.4.2-cp313-cp313-win_arm64.whl", hash = "sha256:0fece1d1f0a89c16b03442eae5c56dc0be0c7883b5d388e0c03f53019a4bfd71", size = 10221082, upload-time = "2026-01-31T23:11:40.392Z" }, + { url = "https://files.pythonhosted.org/packages/25/a1/9510aa43555b44781968935c7548a8926274f815de42ad3997e9e83680dd/numpy-2.4.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5633c0da313330fd20c484c78cdd3f9b175b55e1a766c4a174230c6b70ad8262", size = 14815866, upload-time = "2026-01-31T23:11:42.495Z" }, + { url = "https://files.pythonhosted.org/packages/36/30/6bbb5e76631a5ae46e7923dd16ca9d3f1c93cfa8d4ed79a129814a9d8db3/numpy-2.4.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:d9f64d786b3b1dd742c946c42d15b07497ed14af1a1f3ce840cce27daa0ce913", size = 5325631, upload-time = "2026-01-31T23:11:44.7Z" }, + { url = "https://files.pythonhosted.org/packages/46/00/3a490938800c1923b567b3a15cd17896e68052e2145d8662aaf3e1ffc58f/numpy-2.4.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:b21041e8cb6a1eb5312dd1d2f80a94d91efffb7a06b70597d44f1bd2dfc315ab", size = 6646254, upload-time = "2026-01-31T23:11:46.341Z" }, + { url = "https://files.pythonhosted.org/packages/d3/e9/fac0890149898a9b609caa5af7455a948b544746e4b8fe7c212c8edd71f8/numpy-2.4.2-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:00ab83c56211a1d7c07c25e3217ea6695e50a3e2f255053686b081dc0b091a82", size = 15720138, upload-time = "2026-01-31T23:11:48.082Z" }, + { url = "https://files.pythonhosted.org/packages/ea/5c/08887c54e68e1e28df53709f1893ce92932cc6f01f7c3d4dc952f61ffd4e/numpy-2.4.2-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2fb882da679409066b4603579619341c6d6898fc83a8995199d5249f986e8e8f", size = 16655398, upload-time = "2026-01-31T23:11:50.293Z" }, + { url = "https://files.pythonhosted.org/packages/4d/89/253db0fa0e66e9129c745e4ef25631dc37d5f1314dad2b53e907b8538e6d/numpy-2.4.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:66cb9422236317f9d44b67b4d18f44efe6e9c7f8794ac0462978513359461554", size = 17079064, upload-time = "2026-01-31T23:11:52.927Z" }, + { url = "https://files.pythonhosted.org/packages/2a/d5/cbade46ce97c59c6c3da525e8d95b7abe8a42974a1dc5c1d489c10433e88/numpy-2.4.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0f01dcf33e73d80bd8dc0f20a71303abbafa26a19e23f6b68d1aa9990af90257", size = 18379680, upload-time = "2026-01-31T23:11:55.22Z" }, + { url = "https://files.pythonhosted.org/packages/40/62/48f99ae172a4b63d981babe683685030e8a3df4f246c893ea5c6ef99f018/numpy-2.4.2-cp313-cp313t-win32.whl", hash = "sha256:52b913ec40ff7ae845687b0b34d8d93b60cb66dcee06996dd5c99f2fc9328657", size = 6082433, upload-time = "2026-01-31T23:11:58.096Z" }, + { url = "https://files.pythonhosted.org/packages/07/38/e054a61cfe48ad9f1ed0d188e78b7e26859d0b60ef21cd9de4897cdb5326/numpy-2.4.2-cp313-cp313t-win_amd64.whl", hash = "sha256:5eea80d908b2c1f91486eb95b3fb6fab187e569ec9752ab7d9333d2e66bf2d6b", size = 12451181, upload-time = "2026-01-31T23:11:59.782Z" }, + { url = "https://files.pythonhosted.org/packages/6e/a4/a05c3a6418575e185dd84d0b9680b6bb2e2dc3e4202f036b7b4e22d6e9dc/numpy-2.4.2-cp313-cp313t-win_arm64.whl", hash = "sha256:fd49860271d52127d61197bb50b64f58454e9f578cb4b2c001a6de8b1f50b0b1", size = 10290756, upload-time = "2026-01-31T23:12:02.438Z" }, { url = "https://files.pythonhosted.org/packages/18/88/b7df6050bf18fdcfb7046286c6535cabbdd2064a3440fca3f069d319c16e/numpy-2.4.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:444be170853f1f9d528428eceb55f12918e4fda5d8805480f36a002f1415e09b", size = 16663092, upload-time = "2026-01-31T23:12:04.521Z" }, { url = "https://files.pythonhosted.org/packages/25/7a/1fee4329abc705a469a4afe6e69b1ef7e915117747886327104a8493a955/numpy-2.4.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d1240d50adff70c2a88217698ca844723068533f3f5c5fa6ee2e3220e3bdb000", size = 14698770, upload-time = "2026-01-31T23:12:06.96Z" }, { url = "https://files.pythonhosted.org/packages/fb/0b/f9e49ba6c923678ad5bc38181c08ac5e53b7a5754dbca8e581aa1a56b1ff/numpy-2.4.2-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:7cdde6de52fb6664b00b056341265441192d1291c130e99183ec0d4b110ff8b1", size = 5208562, upload-time = "2026-01-31T23:12:09.632Z" }, @@ -1135,6 +1486,29 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/2e/0c/b28ed414f080ee0ad153f848586d61d1878f91689950f037f976ce15f6c8/pandas-3.0.1.tar.gz", hash = "sha256:4186a699674af418f655dbd420ed87f50d56b4cd6603784279d9eef6627823c8", size = 4641901, upload-time = "2026-02-17T22:20:16.434Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/37/51/b467209c08dae2c624873d7491ea47d2b47336e5403309d433ea79c38571/pandas-3.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:476f84f8c20c9f5bc47252b66b4bb25e1a9fc2fa98cead96744d8116cb85771d", size = 10344357, upload-time = "2026-02-17T22:18:38.262Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f1/e2567ffc8951ab371db2e40b2fe068e36b81d8cf3260f06ae508700e5504/pandas-3.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0ab749dfba921edf641d4036c4c21c0b3ea70fea478165cb98a998fb2a261955", size = 9884543, upload-time = "2026-02-17T22:18:41.476Z" }, + { url = "https://files.pythonhosted.org/packages/d7/39/327802e0b6d693182403c144edacbc27eb82907b57062f23ef5a4c4a5ea7/pandas-3.0.1-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b8e36891080b87823aff3640c78649b91b8ff6eea3c0d70aeabd72ea43ab069b", size = 10396030, upload-time = "2026-02-17T22:18:43.822Z" }, + { url = "https://files.pythonhosted.org/packages/3d/fe/89d77e424365280b79d99b3e1e7d606f5165af2f2ecfaf0c6d24c799d607/pandas-3.0.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:532527a701281b9dd371e2f582ed9094f4c12dd9ffb82c0c54ee28d8ac9520c4", size = 10876435, upload-time = "2026-02-17T22:18:45.954Z" }, + { url = "https://files.pythonhosted.org/packages/b5/a6/2a75320849dd154a793f69c951db759aedb8d1dd3939eeacda9bdcfa1629/pandas-3.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:356e5c055ed9b0da1580d465657bc7d00635af4fd47f30afb23025352ba764d1", size = 11405133, upload-time = "2026-02-17T22:18:48.533Z" }, + { url = "https://files.pythonhosted.org/packages/58/53/1d68fafb2e02d7881df66aa53be4cd748d25cbe311f3b3c85c93ea5d30ca/pandas-3.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9d810036895f9ad6345b8f2a338dd6998a74e8483847403582cab67745bff821", size = 11932065, upload-time = "2026-02-17T22:18:50.837Z" }, + { url = "https://files.pythonhosted.org/packages/75/08/67cc404b3a966b6df27b38370ddd96b3b023030b572283d035181854aac5/pandas-3.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:536232a5fe26dd989bd633e7a0c450705fdc86a207fec7254a55e9a22950fe43", size = 9741627, upload-time = "2026-02-17T22:18:53.905Z" }, + { url = "https://files.pythonhosted.org/packages/86/4f/caf9952948fb00d23795f09b893d11f1cacb384e666854d87249530f7cbe/pandas-3.0.1-cp312-cp312-win_arm64.whl", hash = "sha256:0f463ebfd8de7f326d38037c7363c6dacb857c5881ab8961fb387804d6daf2f7", size = 9052483, upload-time = "2026-02-17T22:18:57.31Z" }, + { url = "https://files.pythonhosted.org/packages/0b/48/aad6ec4f8d007534c091e9a7172b3ec1b1ee6d99a9cbb936b5eab6c6cf58/pandas-3.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5272627187b5d9c20e55d27caf5f2cd23e286aba25cadf73c8590e432e2b7262", size = 10317509, upload-time = "2026-02-17T22:18:59.498Z" }, + { url = "https://files.pythonhosted.org/packages/a8/14/5990826f779f79148ae9d3a2c39593dc04d61d5d90541e71b5749f35af95/pandas-3.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:661e0f665932af88c7877f31da0dc743fe9c8f2524bdffe23d24fdcb67ef9d56", size = 9860561, upload-time = "2026-02-17T22:19:02.265Z" }, + { url = "https://files.pythonhosted.org/packages/fa/80/f01ff54664b6d70fed71475543d108a9b7c888e923ad210795bef04ffb7d/pandas-3.0.1-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:75e6e292ff898679e47a2199172593d9f6107fd2dd3617c22c2946e97d5df46e", size = 10365506, upload-time = "2026-02-17T22:19:05.017Z" }, + { url = "https://files.pythonhosted.org/packages/f2/85/ab6d04733a7d6ff32bfc8382bf1b07078228f5d6ebec5266b91bfc5c4ff7/pandas-3.0.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1ff8cf1d2896e34343197685f432450ec99a85ba8d90cce2030c5eee2ef98791", size = 10873196, upload-time = "2026-02-17T22:19:07.204Z" }, + { url = "https://files.pythonhosted.org/packages/48/a9/9301c83d0b47c23ac5deab91c6b39fd98d5b5db4d93b25df8d381451828f/pandas-3.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:eca8b4510f6763f3d37359c2105df03a7a221a508f30e396a51d0713d462e68a", size = 11370859, upload-time = "2026-02-17T22:19:09.436Z" }, + { url = "https://files.pythonhosted.org/packages/59/fe/0c1fc5bd2d29c7db2ab372330063ad555fb83e08422829c785f5ec2176ca/pandas-3.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:06aff2ad6f0b94a17822cf8b83bbb563b090ed82ff4fe7712db2ce57cd50d9b8", size = 11924584, upload-time = "2026-02-17T22:19:11.562Z" }, + { url = "https://files.pythonhosted.org/packages/d6/7d/216a1588b65a7aa5f4535570418a599d943c85afb1d95b0876fc00aa1468/pandas-3.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:9fea306c783e28884c29057a1d9baa11a349bbf99538ec1da44c8476563d1b25", size = 9742769, upload-time = "2026-02-17T22:19:13.926Z" }, + { url = "https://files.pythonhosted.org/packages/c4/cb/810a22a6af9a4e97c8ab1c946b47f3489c5bca5adc483ce0ffc84c9cc768/pandas-3.0.1-cp313-cp313-win_arm64.whl", hash = "sha256:a8d37a43c52917427e897cb2e429f67a449327394396a81034a4449b99afda59", size = 9043855, upload-time = "2026-02-17T22:19:16.09Z" }, + { url = "https://files.pythonhosted.org/packages/92/fa/423c89086cca1f039cf1253c3ff5b90f157b5b3757314aa635f6bf3e30aa/pandas-3.0.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d54855f04f8246ed7b6fc96b05d4871591143c46c0b6f4af874764ed0d2d6f06", size = 10752673, upload-time = "2026-02-17T22:19:18.304Z" }, + { url = "https://files.pythonhosted.org/packages/22/23/b5a08ec1f40020397f0faba72f1e2c11f7596a6169c7b3e800abff0e433f/pandas-3.0.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4e1b677accee34a09e0dc2ce5624e4a58a1870ffe56fc021e9caf7f23cd7668f", size = 10404967, upload-time = "2026-02-17T22:19:20.726Z" }, + { url = "https://files.pythonhosted.org/packages/5c/81/94841f1bb4afdc2b52a99daa895ac2c61600bb72e26525ecc9543d453ebc/pandas-3.0.1-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a9cabbdcd03f1b6cd254d6dda8ae09b0252524be1592594c00b7895916cb1324", size = 10320575, upload-time = "2026-02-17T22:19:24.919Z" }, + { url = "https://files.pythonhosted.org/packages/0a/8b/2ae37d66a5342a83adadfd0cb0b4bf9c3c7925424dd5f40d15d6cfaa35ee/pandas-3.0.1-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5ae2ab1f166668b41e770650101e7090824fd34d17915dd9cd479f5c5e0065e9", size = 10710921, upload-time = "2026-02-17T22:19:27.181Z" }, + { url = "https://files.pythonhosted.org/packages/a2/61/772b2e2757855e232b7ccf7cb8079a5711becb3a97f291c953def15a833f/pandas-3.0.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6bf0603c2e30e2cafac32807b06435f28741135cb8697eae8b28c7d492fc7d76", size = 11334191, upload-time = "2026-02-17T22:19:29.411Z" }, + { url = "https://files.pythonhosted.org/packages/1b/08/b16c6df3ef555d8495d1d265a7963b65be166785d28f06a350913a4fac78/pandas-3.0.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6c426422973973cae1f4a23e51d4ae85974f44871b24844e4f7de752dd877098", size = 11782256, upload-time = "2026-02-17T22:19:32.34Z" }, + { url = "https://files.pythonhosted.org/packages/55/80/178af0594890dee17e239fca96d3d8670ba0f5ff59b7d0439850924a9c09/pandas-3.0.1-cp313-cp313t-win_amd64.whl", hash = "sha256:b03f91ae8c10a85c1613102c7bef5229b5379f343030a3ccefeca8a33414cf35", size = 10485047, upload-time = "2026-02-17T22:19:34.605Z" }, { url = "https://files.pythonhosted.org/packages/bb/8b/4bb774a998b97e6c2fd62a9e6cfdaae133b636fd1c468f92afb4ae9a447a/pandas-3.0.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:99d0f92ed92d3083d140bf6b97774f9f13863924cf3f52a70711f4e7588f9d0a", size = 10322465, upload-time = "2026-02-17T22:19:36.803Z" }, { url = "https://files.pythonhosted.org/packages/72/3a/5b39b51c64159f470f1ca3b1c2a87da290657ca022f7cd11442606f607d1/pandas-3.0.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3b66857e983208654294bb6477b8a63dee26b37bdd0eb34d010556e91261784f", size = 9910632, upload-time = "2026-02-17T22:19:39.001Z" }, { url = "https://files.pythonhosted.org/packages/4e/f7/b449ffb3f68c11da12fc06fbf6d2fa3a41c41e17d0284d23a79e1c13a7e4/pandas-3.0.1-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:56cf59638bf24dc9bdf2154c81e248b3289f9a09a6d04e63608c159022352749", size = 10440535, upload-time = "2026-02-17T22:19:41.157Z" }, @@ -1181,6 +1555,26 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/cb/72/9a51afa0a822b09e286c4cb827ed7b00bc818dac7bd11a5f161e493a217d/pendulum-3.2.0.tar.gz", hash = "sha256:e80feda2d10fa3ff8b1526715f7d33dcb7e08494b3088f2c8a3ac92d4a4331ce", size = 86912, upload-time = "2026-01-30T11:22:24.093Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/41/56/dd0ea9f97d25a0763cda09e2217563b45714786118d8c68b0b745395d6eb/pendulum-3.2.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:bf0b489def51202a39a2a665dcc4162d5e46934a740fe4c4fe3068979610156c", size = 337830, upload-time = "2026-01-30T11:21:08.298Z" }, + { url = "https://files.pythonhosted.org/packages/cf/98/83d62899bf7226fc12396de4bc1fb2b5da27e451c7c60790043aaf8b4731/pendulum-3.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:937a529aa302efa18dcf25e53834964a87ffb2df8f80e3669ab7757a6126beaf", size = 327574, upload-time = "2026-01-30T11:21:09.715Z" }, + { url = "https://files.pythonhosted.org/packages/76/fa/ff2aa992b23f0543c709b1a3f3f9ed760ec71fd02c8bb01f93bf008b52e4/pendulum-3.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85c7689defc65c4dc29bf257f7cca55d210fabb455de9476e1748d2ab2ae80d7", size = 339891, upload-time = "2026-01-30T11:21:11.089Z" }, + { url = "https://files.pythonhosted.org/packages/c5/4e/25b4fa11d19503d50d7b52d7ef943c0f20fd54422aaeb9e38f588c815c50/pendulum-3.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d5e216e5a412563ea2ecf5de467dcf3d02717947fcdabe6811d5ee360726b02b", size = 373726, upload-time = "2026-01-30T11:21:12.493Z" }, + { url = "https://files.pythonhosted.org/packages/4f/30/0acad6396c4e74e5c689aa4f0b0c49e2ecdcfce368e7b5bf35ca1c0fc61a/pendulum-3.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a2af22eeec438fbaac72bb7fba783e0950a514fba980d9a32db394b51afccec", size = 379827, upload-time = "2026-01-30T11:21:14.08Z" }, + { url = "https://files.pythonhosted.org/packages/3a/f7/e6a2fdf2a23d59b4b48b8fa89e8d4bf2dd371aea2c6ba8fcecec20a4acb9/pendulum-3.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3159cceb54f5aa8b85b141c7f0ce3fac8bdd1ffdc7c79e67dca9133eac7c4d11", size = 348921, upload-time = "2026-01-30T11:21:15.816Z" }, + { url = "https://files.pythonhosted.org/packages/7f/f2/c15fa7f9ad4e181aa469b6040b574988bd108ccdf4ae509ad224f9e4db44/pendulum-3.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c39ea5e9ffa20ea8bae986d00e0908bd537c8468b71d6b6503ab0b4c3d76e0ea", size = 517188, upload-time = "2026-01-30T11:21:17.835Z" }, + { url = "https://files.pythonhosted.org/packages/47/c7/5f80b12ee88ec26e930c3a5a602608a63c29cf60c81a0eb066d583772550/pendulum-3.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e5afc753e570cce1f44197676371f68953f7d4f022303d141bb09f804d5fe6d7", size = 561833, upload-time = "2026-01-30T11:21:19.232Z" }, + { url = "https://files.pythonhosted.org/packages/90/15/1ac481626cb63db751f6281e294661947c1f0321ebe5d1c532a3b51a8006/pendulum-3.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:fd55c12560816d9122ca2142d9e428f32c0c083bf77719320b1767539c7a3a3b", size = 258725, upload-time = "2026-01-30T11:21:20.558Z" }, + { url = "https://files.pythonhosted.org/packages/40/ae/50b0398d7d027eb70a3e1e336de7b6e599c6b74431cb7d3863287e1292bb/pendulum-3.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:faef52a7ed99729f0838353b956f3fabf6c550c062db247e9e2fc2b48fcb9457", size = 253089, upload-time = "2026-01-30T11:21:22.497Z" }, + { url = "https://files.pythonhosted.org/packages/27/8c/400c8b8dbd7524424f3d9902ded64741e82e5e321d1aabbd68ade89e71cf/pendulum-3.2.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:addb0512f919fe5b70c8ee534ee71c775630d3efe567ea5763d92acff857cfc3", size = 337820, upload-time = "2026-01-30T11:21:24.305Z" }, + { url = "https://files.pythonhosted.org/packages/59/38/7c16f26cc55d9206d71da294ce6857d0da381e26bc9e0c2a069424c2b173/pendulum-3.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3aaa50342dc174acebdc21089315012e63789353957b39ac83cac9f9fc8d1075", size = 327551, upload-time = "2026-01-30T11:21:25.747Z" }, + { url = "https://files.pythonhosted.org/packages/0b/cd/f36ec5d56d55104232380fdbf84ff53cc05607574af3cbdc8a43991ac8a7/pendulum-3.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:927e9c9ab52ff68e71b76dd410e5f1cd78f5ea6e7f0a9f5eb549aea16a4d5354", size = 339894, upload-time = "2026-01-30T11:21:27.229Z" }, + { url = "https://files.pythonhosted.org/packages/aa/4e/b9a1e546519c3a92d5bc17787cea925e06a20def2ae344fa136d2fc40338/pendulum-3.2.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:249d18f5543c9f43aba3bd77b34864ec8cf6f64edbead405f442e23c94fce63d", size = 373766, upload-time = "2026-01-30T11:21:28.642Z" }, + { url = "https://files.pythonhosted.org/packages/ea/a6/6471ab87ae2260594501f071586a765fc894817043b7d2d4b04e2eff4f31/pendulum-3.2.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c644cc15eec5fb02291f0f193195156780fd5a0affd7a349592403826d1a35e", size = 379837, upload-time = "2026-01-30T11:21:30.637Z" }, + { url = "https://files.pythonhosted.org/packages/0d/79/0ba0c14e862388f7b822626e6e989163c23bebe7f96de5ec4b207cbe7c3d/pendulum-3.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:063ab61af953bb56ad5bc8e131fd0431c915ed766d90ccecd7549c8090b51004", size = 348904, upload-time = "2026-01-30T11:21:32.436Z" }, + { url = "https://files.pythonhosted.org/packages/17/34/df922c7c0b12719589d4954bfa5bdca9e02bcde220f5c5c1838a87118960/pendulum-3.2.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:26a3ae26c9dd70a4256f1c2f51addc43641813574c0db6ce5664f9861cd93621", size = 517173, upload-time = "2026-01-30T11:21:34.428Z" }, + { url = "https://files.pythonhosted.org/packages/87/ec/3b9e061eeee97b72a47c1434ee03f6d85f0284d9285d92b12b0fff2d19ac/pendulum-3.2.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:2b10d91dc00f424444a42f47c69e6b3bfd79376f330179dc06bc342184b35f9a", size = 561744, upload-time = "2026-01-30T11:21:35.861Z" }, + { url = "https://files.pythonhosted.org/packages/fd/7e/f12fdb6070b7975c1fcfa5685dbe4ab73c788878a71f4d1d7e3c87979e37/pendulum-3.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:63070ff03e30a57b16c8e793ee27da8dac4123c1d6e0cf74c460ce9ee8a64aa4", size = 258746, upload-time = "2026-01-30T11:21:37.782Z" }, + { url = "https://files.pythonhosted.org/packages/c9/b8/5abd872056357f069ae34a9b24a75ac58e79092d16201d779a8dd31386bb/pendulum-3.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:c8dde63e2796b62070a49ce813ce200aba9186130307f04ec78affcf6c2e8122", size = 253028, upload-time = "2026-01-30T11:21:39.381Z" }, { url = "https://files.pythonhosted.org/packages/82/99/5b9cc823862450910bcb2c7cdc6884c0939b268639146d30e4a4f55eb1f1/pendulum-3.2.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:c17ac069e88c5a1e930a5ae0ef17357a14b9cc5a28abadda74eaa8106d241c8e", size = 338281, upload-time = "2026-01-30T11:21:40.812Z" }, { url = "https://files.pythonhosted.org/packages/cd/3a/64a35260f6ac36c0ad50eeb5f1a465b98b0d7603f79a5c2077c41326d639/pendulum-3.2.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e1fbb540edecb21f8244aebfb05a1f2333ddc6c7819378c099d4a61cc91ae93c", size = 328030, upload-time = "2026-01-30T11:21:42.778Z" }, { url = "https://files.pythonhosted.org/packages/da/6b/1140e09310035a2afb05bb90a2b8fbda9d3222e03b92de9533123afe6b65/pendulum-3.2.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a8c67fb9a1fe8fc1adae2cc01b0c292b268c12475b4609ff4aed71c9dd367b4d", size = 340206, upload-time = "2026-01-30T11:21:44.148Z" }, @@ -1227,6 +1621,51 @@ version = "0.4.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/9e/da/e9fc233cf63743258bff22b3dfa7ea5baef7b5bc324af47a0ad89b8ffc6f/propcache-0.4.1.tar.gz", hash = "sha256:f48107a8c637e80362555f37ecf49abe20370e557cc4ab374f04ec4423c97c3d", size = 46442, upload-time = "2025-10-08T19:49:02.291Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/a2/0f/f17b1b2b221d5ca28b4b876e8bb046ac40466513960646bda8e1853cdfa2/propcache-0.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e153e9cd40cc8945138822807139367f256f89c6810c2634a4f6902b52d3b4e2", size = 80061, upload-time = "2025-10-08T19:46:46.075Z" }, + { url = "https://files.pythonhosted.org/packages/76/47/8ccf75935f51448ba9a16a71b783eb7ef6b9ee60f5d14c7f8a8a79fbeed7/propcache-0.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cd547953428f7abb73c5ad82cbb32109566204260d98e41e5dfdc682eb7f8403", size = 46037, upload-time = "2025-10-08T19:46:47.23Z" }, + { url = "https://files.pythonhosted.org/packages/0a/b6/5c9a0e42df4d00bfb4a3cbbe5cf9f54260300c88a0e9af1f47ca5ce17ac0/propcache-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f048da1b4f243fc44f205dfd320933a951b8d89e0afd4c7cacc762a8b9165207", size = 47324, upload-time = "2025-10-08T19:46:48.384Z" }, + { url = "https://files.pythonhosted.org/packages/9e/d3/6c7ee328b39a81ee877c962469f1e795f9db87f925251efeb0545e0020d0/propcache-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ec17c65562a827bba85e3872ead335f95405ea1674860d96483a02f5c698fa72", size = 225505, upload-time = "2025-10-08T19:46:50.055Z" }, + { url = "https://files.pythonhosted.org/packages/01/5d/1c53f4563490b1d06a684742cc6076ef944bc6457df6051b7d1a877c057b/propcache-0.4.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:405aac25c6394ef275dee4c709be43745d36674b223ba4eb7144bf4d691b7367", size = 230242, upload-time = "2025-10-08T19:46:51.815Z" }, + { url = "https://files.pythonhosted.org/packages/20/e1/ce4620633b0e2422207c3cb774a0ee61cac13abc6217763a7b9e2e3f4a12/propcache-0.4.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0013cb6f8dde4b2a2f66903b8ba740bdfe378c943c4377a200551ceb27f379e4", size = 238474, upload-time = "2025-10-08T19:46:53.208Z" }, + { url = "https://files.pythonhosted.org/packages/46/4b/3aae6835b8e5f44ea6a68348ad90f78134047b503765087be2f9912140ea/propcache-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15932ab57837c3368b024473a525e25d316d8353016e7cc0e5ba9eb343fbb1cf", size = 221575, upload-time = "2025-10-08T19:46:54.511Z" }, + { url = "https://files.pythonhosted.org/packages/6e/a5/8a5e8678bcc9d3a1a15b9a29165640d64762d424a16af543f00629c87338/propcache-0.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:031dce78b9dc099f4c29785d9cf5577a3faf9ebf74ecbd3c856a7b92768c3df3", size = 216736, upload-time = "2025-10-08T19:46:56.212Z" }, + { url = "https://files.pythonhosted.org/packages/f1/63/b7b215eddeac83ca1c6b934f89d09a625aa9ee4ba158338854c87210cc36/propcache-0.4.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ab08df6c9a035bee56e31af99be621526bd237bea9f32def431c656b29e41778", size = 213019, upload-time = "2025-10-08T19:46:57.595Z" }, + { url = "https://files.pythonhosted.org/packages/57/74/f580099a58c8af587cac7ba19ee7cb418506342fbbe2d4a4401661cca886/propcache-0.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4d7af63f9f93fe593afbf104c21b3b15868efb2c21d07d8732c0c4287e66b6a6", size = 220376, upload-time = "2025-10-08T19:46:59.067Z" }, + { url = "https://files.pythonhosted.org/packages/c4/ee/542f1313aff7eaf19c2bb758c5d0560d2683dac001a1c96d0774af799843/propcache-0.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cfc27c945f422e8b5071b6e93169679e4eb5bf73bbcbf1ba3ae3a83d2f78ebd9", size = 226988, upload-time = "2025-10-08T19:47:00.544Z" }, + { url = "https://files.pythonhosted.org/packages/8f/18/9c6b015dd9c6930f6ce2229e1f02fb35298b847f2087ea2b436a5bfa7287/propcache-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:35c3277624a080cc6ec6f847cbbbb5b49affa3598c4535a0a4682a697aaa5c75", size = 215615, upload-time = "2025-10-08T19:47:01.968Z" }, + { url = "https://files.pythonhosted.org/packages/80/9e/e7b85720b98c45a45e1fca6a177024934dc9bc5f4d5dd04207f216fc33ed/propcache-0.4.1-cp312-cp312-win32.whl", hash = "sha256:671538c2262dadb5ba6395e26c1731e1d52534bfe9ae56d0b5573ce539266aa8", size = 38066, upload-time = "2025-10-08T19:47:03.503Z" }, + { url = "https://files.pythonhosted.org/packages/54/09/d19cff2a5aaac632ec8fc03737b223597b1e347416934c1b3a7df079784c/propcache-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:cb2d222e72399fcf5890d1d5cc1060857b9b236adff2792ff48ca2dfd46c81db", size = 41655, upload-time = "2025-10-08T19:47:04.973Z" }, + { url = "https://files.pythonhosted.org/packages/68/ab/6b5c191bb5de08036a8c697b265d4ca76148efb10fa162f14af14fb5f076/propcache-0.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:204483131fb222bdaaeeea9f9e6c6ed0cac32731f75dfc1d4a567fc1926477c1", size = 37789, upload-time = "2025-10-08T19:47:06.077Z" }, + { url = "https://files.pythonhosted.org/packages/bf/df/6d9c1b6ac12b003837dde8a10231a7344512186e87b36e855bef32241942/propcache-0.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:43eedf29202c08550aac1d14e0ee619b0430aaef78f85864c1a892294fbc28cf", size = 77750, upload-time = "2025-10-08T19:47:07.648Z" }, + { url = "https://files.pythonhosted.org/packages/8b/e8/677a0025e8a2acf07d3418a2e7ba529c9c33caf09d3c1f25513023c1db56/propcache-0.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d62cdfcfd89ccb8de04e0eda998535c406bf5e060ffd56be6c586cbcc05b3311", size = 44780, upload-time = "2025-10-08T19:47:08.851Z" }, + { url = "https://files.pythonhosted.org/packages/89/a4/92380f7ca60f99ebae761936bc48a72a639e8a47b29050615eef757cb2a7/propcache-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cae65ad55793da34db5f54e4029b89d3b9b9490d8abe1b4c7ab5d4b8ec7ebf74", size = 46308, upload-time = "2025-10-08T19:47:09.982Z" }, + { url = "https://files.pythonhosted.org/packages/2d/48/c5ac64dee5262044348d1d78a5f85dd1a57464a60d30daee946699963eb3/propcache-0.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:333ddb9031d2704a301ee3e506dc46b1fe5f294ec198ed6435ad5b6a085facfe", size = 208182, upload-time = "2025-10-08T19:47:11.319Z" }, + { url = "https://files.pythonhosted.org/packages/c6/0c/cd762dd011a9287389a6a3eb43aa30207bde253610cca06824aeabfe9653/propcache-0.4.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:fd0858c20f078a32cf55f7e81473d96dcf3b93fd2ccdb3d40fdf54b8573df3af", size = 211215, upload-time = "2025-10-08T19:47:13.146Z" }, + { url = "https://files.pythonhosted.org/packages/30/3e/49861e90233ba36890ae0ca4c660e95df565b2cd15d4a68556ab5865974e/propcache-0.4.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:678ae89ebc632c5c204c794f8dab2837c5f159aeb59e6ed0539500400577298c", size = 218112, upload-time = "2025-10-08T19:47:14.913Z" }, + { url = "https://files.pythonhosted.org/packages/f1/8b/544bc867e24e1bd48f3118cecd3b05c694e160a168478fa28770f22fd094/propcache-0.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d472aeb4fbf9865e0c6d622d7f4d54a4e101a89715d8904282bb5f9a2f476c3f", size = 204442, upload-time = "2025-10-08T19:47:16.277Z" }, + { url = "https://files.pythonhosted.org/packages/50/a6/4282772fd016a76d3e5c0df58380a5ea64900afd836cec2c2f662d1b9bb3/propcache-0.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4d3df5fa7e36b3225954fba85589da77a0fe6a53e3976de39caf04a0db4c36f1", size = 199398, upload-time = "2025-10-08T19:47:17.962Z" }, + { url = "https://files.pythonhosted.org/packages/3e/ec/d8a7cd406ee1ddb705db2139f8a10a8a427100347bd698e7014351c7af09/propcache-0.4.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:ee17f18d2498f2673e432faaa71698032b0127ebf23ae5974eeaf806c279df24", size = 196920, upload-time = "2025-10-08T19:47:19.355Z" }, + { url = "https://files.pythonhosted.org/packages/f6/6c/f38ab64af3764f431e359f8baf9e0a21013e24329e8b85d2da32e8ed07ca/propcache-0.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:580e97762b950f993ae618e167e7be9256b8353c2dcd8b99ec100eb50f5286aa", size = 203748, upload-time = "2025-10-08T19:47:21.338Z" }, + { url = "https://files.pythonhosted.org/packages/d6/e3/fa846bd70f6534d647886621388f0a265254d30e3ce47e5c8e6e27dbf153/propcache-0.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:501d20b891688eb8e7aa903021f0b72d5a55db40ffaab27edefd1027caaafa61", size = 205877, upload-time = "2025-10-08T19:47:23.059Z" }, + { url = "https://files.pythonhosted.org/packages/e2/39/8163fc6f3133fea7b5f2827e8eba2029a0277ab2c5beee6c1db7b10fc23d/propcache-0.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a0bd56e5b100aef69bd8562b74b46254e7c8812918d3baa700c8a8009b0af66", size = 199437, upload-time = "2025-10-08T19:47:24.445Z" }, + { url = "https://files.pythonhosted.org/packages/93/89/caa9089970ca49c7c01662bd0eeedfe85494e863e8043565aeb6472ce8fe/propcache-0.4.1-cp313-cp313-win32.whl", hash = "sha256:bcc9aaa5d80322bc2fb24bb7accb4a30f81e90ab8d6ba187aec0744bc302ad81", size = 37586, upload-time = "2025-10-08T19:47:25.736Z" }, + { url = "https://files.pythonhosted.org/packages/f5/ab/f76ec3c3627c883215b5c8080debb4394ef5a7a29be811f786415fc1e6fd/propcache-0.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:381914df18634f5494334d201e98245c0596067504b9372d8cf93f4bb23e025e", size = 40790, upload-time = "2025-10-08T19:47:26.847Z" }, + { url = "https://files.pythonhosted.org/packages/59/1b/e71ae98235f8e2ba5004d8cb19765a74877abf189bc53fc0c80d799e56c3/propcache-0.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:8873eb4460fd55333ea49b7d189749ecf6e55bf85080f11b1c4530ed3034cba1", size = 37158, upload-time = "2025-10-08T19:47:27.961Z" }, + { url = "https://files.pythonhosted.org/packages/83/ce/a31bbdfc24ee0dcbba458c8175ed26089cf109a55bbe7b7640ed2470cfe9/propcache-0.4.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:92d1935ee1f8d7442da9c0c4fa7ac20d07e94064184811b685f5c4fada64553b", size = 81451, upload-time = "2025-10-08T19:47:29.445Z" }, + { url = "https://files.pythonhosted.org/packages/25/9c/442a45a470a68456e710d96cacd3573ef26a1d0a60067e6a7d5e655621ed/propcache-0.4.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:473c61b39e1460d386479b9b2f337da492042447c9b685f28be4f74d3529e566", size = 46374, upload-time = "2025-10-08T19:47:30.579Z" }, + { url = "https://files.pythonhosted.org/packages/f4/bf/b1d5e21dbc3b2e889ea4327044fb16312a736d97640fb8b6aa3f9c7b3b65/propcache-0.4.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c0ef0aaafc66fbd87842a3fe3902fd889825646bc21149eafe47be6072725835", size = 48396, upload-time = "2025-10-08T19:47:31.79Z" }, + { url = "https://files.pythonhosted.org/packages/f4/04/5b4c54a103d480e978d3c8a76073502b18db0c4bc17ab91b3cb5092ad949/propcache-0.4.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95393b4d66bfae908c3ca8d169d5f79cd65636ae15b5e7a4f6e67af675adb0e", size = 275950, upload-time = "2025-10-08T19:47:33.481Z" }, + { url = "https://files.pythonhosted.org/packages/b4/c1/86f846827fb969c4b78b0af79bba1d1ea2156492e1b83dea8b8a6ae27395/propcache-0.4.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c07fda85708bc48578467e85099645167a955ba093be0a2dcba962195676e859", size = 273856, upload-time = "2025-10-08T19:47:34.906Z" }, + { url = "https://files.pythonhosted.org/packages/36/1d/fc272a63c8d3bbad6878c336c7a7dea15e8f2d23a544bda43205dfa83ada/propcache-0.4.1-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:af223b406d6d000830c6f65f1e6431783fc3f713ba3e6cc8c024d5ee96170a4b", size = 280420, upload-time = "2025-10-08T19:47:36.338Z" }, + { url = "https://files.pythonhosted.org/packages/07/0c/01f2219d39f7e53d52e5173bcb09c976609ba30209912a0680adfb8c593a/propcache-0.4.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a78372c932c90ee474559c5ddfffd718238e8673c340dc21fe45c5b8b54559a0", size = 263254, upload-time = "2025-10-08T19:47:37.692Z" }, + { url = "https://files.pythonhosted.org/packages/2d/18/cd28081658ce597898f0c4d174d4d0f3c5b6d4dc27ffafeef835c95eb359/propcache-0.4.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:564d9f0d4d9509e1a870c920a89b2fec951b44bf5ba7d537a9e7c1ccec2c18af", size = 261205, upload-time = "2025-10-08T19:47:39.659Z" }, + { url = "https://files.pythonhosted.org/packages/7a/71/1f9e22eb8b8316701c2a19fa1f388c8a3185082607da8e406a803c9b954e/propcache-0.4.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:17612831fda0138059cc5546f4d12a2aacfb9e47068c06af35c400ba58ba7393", size = 247873, upload-time = "2025-10-08T19:47:41.084Z" }, + { url = "https://files.pythonhosted.org/packages/4a/65/3d4b61f36af2b4eddba9def857959f1016a51066b4f1ce348e0cf7881f58/propcache-0.4.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:41a89040cb10bd345b3c1a873b2bf36413d48da1def52f268a055f7398514874", size = 262739, upload-time = "2025-10-08T19:47:42.51Z" }, + { url = "https://files.pythonhosted.org/packages/2a/42/26746ab087faa77c1c68079b228810436ccd9a5ce9ac85e2b7307195fd06/propcache-0.4.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e35b88984e7fa64aacecea39236cee32dd9bd8c55f57ba8a75cf2399553f9bd7", size = 263514, upload-time = "2025-10-08T19:47:43.927Z" }, + { url = "https://files.pythonhosted.org/packages/94/13/630690fe201f5502d2403dd3cfd451ed8858fe3c738ee88d095ad2ff407b/propcache-0.4.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f8b465489f927b0df505cbe26ffbeed4d6d8a2bbc61ce90eb074ff129ef0ab1", size = 257781, upload-time = "2025-10-08T19:47:45.448Z" }, + { url = "https://files.pythonhosted.org/packages/92/f7/1d4ec5841505f423469efbfc381d64b7b467438cd5a4bbcbb063f3b73d27/propcache-0.4.1-cp313-cp313t-win32.whl", hash = "sha256:2ad890caa1d928c7c2965b48f3a3815c853180831d0e5503d35cf00c472f4717", size = 41396, upload-time = "2025-10-08T19:47:47.202Z" }, + { url = "https://files.pythonhosted.org/packages/48/f0/615c30622316496d2cbbc29f5985f7777d3ada70f23370608c1d3e081c1f/propcache-0.4.1-cp313-cp313t-win_amd64.whl", hash = "sha256:f7ee0e597f495cf415bcbd3da3caa3bd7e816b74d0d52b8145954c5e6fd3ff37", size = 44897, upload-time = "2025-10-08T19:47:48.336Z" }, + { url = "https://files.pythonhosted.org/packages/fd/ca/6002e46eccbe0e33dcd4069ef32f7f1c9e243736e07adca37ae8c4830ec3/propcache-0.4.1-cp313-cp313t-win_arm64.whl", hash = "sha256:929d7cbe1f01bb7baffb33dc14eb5691c95831450a26354cd210a8155170c93a", size = 39789, upload-time = "2025-10-08T19:47:49.876Z" }, { url = "https://files.pythonhosted.org/packages/8e/5c/bca52d654a896f831b8256683457ceddd490ec18d9ec50e97dfd8fc726a8/propcache-0.4.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3f7124c9d820ba5548d431afb4632301acf965db49e666aa21c305cbe8c6de12", size = 78152, upload-time = "2025-10-08T19:47:51.051Z" }, { url = "https://files.pythonhosted.org/packages/65/9b/03b04e7d82a5f54fb16113d839f5ea1ede58a61e90edf515f6577c66fa8f/propcache-0.4.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:c0d4b719b7da33599dfe3b22d3db1ef789210a0597bc650b7cee9c77c2be8c5c", size = 44869, upload-time = "2025-10-08T19:47:52.594Z" }, { url = "https://files.pythonhosted.org/packages/b2/fa/89a8ef0468d5833a23fff277b143d0573897cf75bd56670a6d28126c7d68/propcache-0.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9f302f4783709a78240ebc311b793f123328716a60911d667e0c036bc5dcbded", size = 46596, upload-time = "2025-10-08T19:47:54.073Z" }, @@ -1339,6 +1778,34 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/71/70/23b021c950c2addd24ec408e9ab05d59b035b39d97cdc1130e1bce647bb6/pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e", size = 460952, upload-time = "2025-11-04T13:43:49.098Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/5d/5f6c63eebb5afee93bcaae4ce9a898f3373ca23df3ccaef086d0233a35a7/pydantic_core-2.41.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7", size = 2110990, upload-time = "2025-11-04T13:39:58.079Z" }, + { url = "https://files.pythonhosted.org/packages/aa/32/9c2e8ccb57c01111e0fd091f236c7b371c1bccea0fa85247ac55b1e2b6b6/pydantic_core-2.41.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0", size = 1896003, upload-time = "2025-11-04T13:39:59.956Z" }, + { url = "https://files.pythonhosted.org/packages/68/b8/a01b53cb0e59139fbc9e4fda3e9724ede8de279097179be4ff31f1abb65a/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69", size = 1919200, upload-time = "2025-11-04T13:40:02.241Z" }, + { url = "https://files.pythonhosted.org/packages/38/de/8c36b5198a29bdaade07b5985e80a233a5ac27137846f3bc2d3b40a47360/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75", size = 2052578, upload-time = "2025-11-04T13:40:04.401Z" }, + { url = "https://files.pythonhosted.org/packages/00/b5/0e8e4b5b081eac6cb3dbb7e60a65907549a1ce035a724368c330112adfdd/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05", size = 2208504, upload-time = "2025-11-04T13:40:06.072Z" }, + { url = "https://files.pythonhosted.org/packages/77/56/87a61aad59c7c5b9dc8caad5a41a5545cba3810c3e828708b3d7404f6cef/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc", size = 2335816, upload-time = "2025-11-04T13:40:07.835Z" }, + { url = "https://files.pythonhosted.org/packages/0d/76/941cc9f73529988688a665a5c0ecff1112b3d95ab48f81db5f7606f522d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c", size = 2075366, upload-time = "2025-11-04T13:40:09.804Z" }, + { url = "https://files.pythonhosted.org/packages/d3/43/ebef01f69baa07a482844faaa0a591bad1ef129253ffd0cdaa9d8a7f72d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5", size = 2171698, upload-time = "2025-11-04T13:40:12.004Z" }, + { url = "https://files.pythonhosted.org/packages/b1/87/41f3202e4193e3bacfc2c065fab7706ebe81af46a83d3e27605029c1f5a6/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c", size = 2132603, upload-time = "2025-11-04T13:40:13.868Z" }, + { url = "https://files.pythonhosted.org/packages/49/7d/4c00df99cb12070b6bccdef4a195255e6020a550d572768d92cc54dba91a/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294", size = 2329591, upload-time = "2025-11-04T13:40:15.672Z" }, + { url = "https://files.pythonhosted.org/packages/cc/6a/ebf4b1d65d458f3cda6a7335d141305dfa19bdc61140a884d165a8a1bbc7/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1", size = 2319068, upload-time = "2025-11-04T13:40:17.532Z" }, + { url = "https://files.pythonhosted.org/packages/49/3b/774f2b5cd4192d5ab75870ce4381fd89cf218af999515baf07e7206753f0/pydantic_core-2.41.5-cp312-cp312-win32.whl", hash = "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d", size = 1985908, upload-time = "2025-11-04T13:40:19.309Z" }, + { url = "https://files.pythonhosted.org/packages/86/45/00173a033c801cacf67c190fef088789394feaf88a98a7035b0e40d53dc9/pydantic_core-2.41.5-cp312-cp312-win_amd64.whl", hash = "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815", size = 2020145, upload-time = "2025-11-04T13:40:21.548Z" }, + { url = "https://files.pythonhosted.org/packages/f9/22/91fbc821fa6d261b376a3f73809f907cec5ca6025642c463d3488aad22fb/pydantic_core-2.41.5-cp312-cp312-win_arm64.whl", hash = "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3", size = 1976179, upload-time = "2025-11-04T13:40:23.393Z" }, + { url = "https://files.pythonhosted.org/packages/87/06/8806241ff1f70d9939f9af039c6c35f2360cf16e93c2ca76f184e76b1564/pydantic_core-2.41.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9", size = 2120403, upload-time = "2025-11-04T13:40:25.248Z" }, + { url = "https://files.pythonhosted.org/packages/94/02/abfa0e0bda67faa65fef1c84971c7e45928e108fe24333c81f3bfe35d5f5/pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34", size = 1896206, upload-time = "2025-11-04T13:40:27.099Z" }, + { url = "https://files.pythonhosted.org/packages/15/df/a4c740c0943e93e6500f9eb23f4ca7ec9bf71b19e608ae5b579678c8d02f/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0", size = 1919307, upload-time = "2025-11-04T13:40:29.806Z" }, + { url = "https://files.pythonhosted.org/packages/9a/e3/6324802931ae1d123528988e0e86587c2072ac2e5394b4bc2bc34b61ff6e/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33", size = 2063258, upload-time = "2025-11-04T13:40:33.544Z" }, + { url = "https://files.pythonhosted.org/packages/c9/d4/2230d7151d4957dd79c3044ea26346c148c98fbf0ee6ebd41056f2d62ab5/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e", size = 2214917, upload-time = "2025-11-04T13:40:35.479Z" }, + { url = "https://files.pythonhosted.org/packages/e6/9f/eaac5df17a3672fef0081b6c1bb0b82b33ee89aa5cec0d7b05f52fd4a1fa/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2", size = 2332186, upload-time = "2025-11-04T13:40:37.436Z" }, + { url = "https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586", size = 2073164, upload-time = "2025-11-04T13:40:40.289Z" }, + { url = "https://files.pythonhosted.org/packages/bf/e3/f6e262673c6140dd3305d144d032f7bd5f7497d3871c1428521f19f9efa2/pydantic_core-2.41.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d", size = 2179146, upload-time = "2025-11-04T13:40:42.809Z" }, + { url = "https://files.pythonhosted.org/packages/75/c7/20bd7fc05f0c6ea2056a4565c6f36f8968c0924f19b7d97bbfea55780e73/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740", size = 2137788, upload-time = "2025-11-04T13:40:44.752Z" }, + { url = "https://files.pythonhosted.org/packages/3a/8d/34318ef985c45196e004bc46c6eab2eda437e744c124ef0dbe1ff2c9d06b/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e", size = 2340133, upload-time = "2025-11-04T13:40:46.66Z" }, + { url = "https://files.pythonhosted.org/packages/9c/59/013626bf8c78a5a5d9350d12e7697d3d4de951a75565496abd40ccd46bee/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858", size = 2324852, upload-time = "2025-11-04T13:40:48.575Z" }, + { url = "https://files.pythonhosted.org/packages/1a/d9/c248c103856f807ef70c18a4f986693a46a8ffe1602e5d361485da502d20/pydantic_core-2.41.5-cp313-cp313-win32.whl", hash = "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36", size = 1994679, upload-time = "2025-11-04T13:40:50.619Z" }, + { url = "https://files.pythonhosted.org/packages/9e/8b/341991b158ddab181cff136acd2552c9f35bd30380422a639c0671e99a91/pydantic_core-2.41.5-cp313-cp313-win_amd64.whl", hash = "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11", size = 2019766, upload-time = "2025-11-04T13:40:52.631Z" }, + { url = "https://files.pythonhosted.org/packages/73/7d/f2f9db34af103bea3e09735bb40b021788a5e834c81eedb541991badf8f5/pydantic_core-2.41.5-cp313-cp313-win_arm64.whl", hash = "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd", size = 1981005, upload-time = "2025-11-04T13:40:54.734Z" }, { url = "https://files.pythonhosted.org/packages/ea/28/46b7c5c9635ae96ea0fbb779e271a38129df2550f763937659ee6c5dbc65/pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a", size = 2119622, upload-time = "2025-11-04T13:40:56.68Z" }, { url = "https://files.pythonhosted.org/packages/74/1a/145646e5687e8d9a1e8d09acb278c8535ebe9e972e1f162ed338a622f193/pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14", size = 1891725, upload-time = "2025-11-04T13:40:58.807Z" }, { url = "https://files.pythonhosted.org/packages/23/04/e89c29e267b8060b40dca97bfc64a19b2a3cf99018167ea1677d96368273/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1", size = 1915040, upload-time = "2025-11-04T13:41:00.853Z" }, @@ -1367,6 +1834,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5c/96/5fb7d8c3c17bc8c62fdb031c47d77a1af698f1d7a406b0f79aaa1338f9ad/pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa", size = 1988906, upload-time = "2025-11-04T13:41:56.606Z" }, { url = "https://files.pythonhosted.org/packages/22/ed/182129d83032702912c2e2d8bbe33c036f342cc735737064668585dac28f/pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c", size = 1981607, upload-time = "2025-11-04T13:41:58.889Z" }, { url = "https://files.pythonhosted.org/packages/9f/ed/068e41660b832bb0b1aa5b58011dea2a3fe0ba7861ff38c4d4904c1c1a99/pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008", size = 1974769, upload-time = "2025-11-04T13:42:01.186Z" }, + { url = "https://files.pythonhosted.org/packages/09/32/59b0c7e63e277fa7911c2fc70ccfb45ce4b98991e7ef37110663437005af/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd", size = 2110495, upload-time = "2025-11-04T13:42:49.689Z" }, + { url = "https://files.pythonhosted.org/packages/aa/81/05e400037eaf55ad400bcd318c05bb345b57e708887f07ddb2d20e3f0e98/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc", size = 1915388, upload-time = "2025-11-04T13:42:52.215Z" }, + { url = "https://files.pythonhosted.org/packages/6e/0d/e3549b2399f71d56476b77dbf3cf8937cec5cd70536bdc0e374a421d0599/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56", size = 1942879, upload-time = "2025-11-04T13:42:56.483Z" }, + { url = "https://files.pythonhosted.org/packages/f7/07/34573da085946b6a313d7c42f82f16e8920bfd730665de2d11c0c37a74b5/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b", size = 2139017, upload-time = "2025-11-04T13:42:59.471Z" }, ] [[package]] @@ -1519,6 +1990,12 @@ name = "pywin32" version = "311" source = { registry = "https://pypi.org/simple" } wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/ab/01ea1943d4eba0f850c3c61e78e8dd59757ff815ff3ccd0a84de5f541f42/pywin32-311-cp312-cp312-win32.whl", hash = "sha256:750ec6e621af2b948540032557b10a2d43b0cee2ae9758c54154d711cc852d31", size = 8706543, upload-time = "2025-07-14T20:13:20.765Z" }, + { url = "https://files.pythonhosted.org/packages/d1/a8/a0e8d07d4d051ec7502cd58b291ec98dcc0c3fff027caad0470b72cfcc2f/pywin32-311-cp312-cp312-win_amd64.whl", hash = "sha256:b8c095edad5c211ff31c05223658e71bf7116daa0ecf3ad85f3201ea3190d067", size = 9495040, upload-time = "2025-07-14T20:13:22.543Z" }, + { url = "https://files.pythonhosted.org/packages/ba/3a/2ae996277b4b50f17d61f0603efd8253cb2d79cc7ae159468007b586396d/pywin32-311-cp312-cp312-win_arm64.whl", hash = "sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852", size = 8710102, upload-time = "2025-07-14T20:13:24.682Z" }, + { url = "https://files.pythonhosted.org/packages/a5/be/3fd5de0979fcb3994bfee0d65ed8ca9506a8a1260651b86174f6a86f52b3/pywin32-311-cp313-cp313-win32.whl", hash = "sha256:f95ba5a847cba10dd8c4d8fefa9f2a6cf283b8b88ed6178fa8a6c1ab16054d0d", size = 8705700, upload-time = "2025-07-14T20:13:26.471Z" }, + { url = "https://files.pythonhosted.org/packages/e3/28/e0a1909523c6890208295a29e05c2adb2126364e289826c0a8bc7297bd5c/pywin32-311-cp313-cp313-win_amd64.whl", hash = "sha256:718a38f7e5b058e76aee1c56ddd06908116d35147e133427e59a3983f703a20d", size = 9494700, upload-time = "2025-07-14T20:13:28.243Z" }, + { url = "https://files.pythonhosted.org/packages/04/bf/90339ac0f55726dce7d794e6d79a18a91265bdf3aa70b6b9ca52f35e022a/pywin32-311-cp313-cp313-win_arm64.whl", hash = "sha256:7b4075d959648406202d92a2310cb990fea19b535c7f4a78d3f5e10b926eeb8a", size = 8709318, upload-time = "2025-07-14T20:13:30.348Z" }, { url = "https://files.pythonhosted.org/packages/c9/31/097f2e132c4f16d99a22bfb777e0fd88bd8e1c634304e102f313af69ace5/pywin32-311-cp314-cp314-win32.whl", hash = "sha256:b7a2c10b93f8986666d0c803ee19b5990885872a7de910fc460f9b0c2fbf92ee", size = 8840714, upload-time = "2025-07-14T20:13:32.449Z" }, { url = "https://files.pythonhosted.org/packages/90/4b/07c77d8ba0e01349358082713400435347df8426208171ce297da32c313d/pywin32-311-cp314-cp314-win_amd64.whl", hash = "sha256:3aca44c046bd2ed8c90de9cb8427f581c479e594e99b5c0bb19b29c10fd6cb87", size = 9656800, upload-time = "2025-07-14T20:13:34.312Z" }, { url = "https://files.pythonhosted.org/packages/c0/d2/21af5c535501a7233e734b8af901574572da66fcc254cb35d0609c9080dd/pywin32-311-cp314-cp314-win_arm64.whl", hash = "sha256:a508e2d9025764a8270f93111a970e1d0fbfc33f4153b388bb649b7eec4f9b42", size = 8932540, upload-time = "2025-07-14T20:13:36.379Z" }, @@ -1539,6 +2016,26 @@ version = "6.0.3" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" }, + { url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" }, + { url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" }, + { url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" }, + { url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" }, + { url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" }, + { url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" }, + { url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" }, + { url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" }, + { url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" }, + { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, + { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, + { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, + { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, + { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, + { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, + { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, + { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, + { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, @@ -1575,6 +2072,7 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "rpds-py" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/2f/db/98b5c277be99dd18bfd91dd04e1b759cad18d1a338188c936e92f921c7e2/referencing-0.36.2.tar.gz", hash = "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa", size = 74744, upload-time = "2025-01-25T08:48:16.138Z" } wheels = [ @@ -1587,6 +2085,54 @@ version = "2026.2.19" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/ff/c0/d8079d4f6342e4cec5c3e7d7415b5cd3e633d5f4124f7a4626908dbe84c7/regex-2026.2.19.tar.gz", hash = "sha256:6fb8cb09b10e38f3ae17cc6dc04a1df77762bd0351b6ba9041438e7cc85ec310", size = 414973, upload-time = "2026-02-19T19:03:47.899Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/73/13b39c7c9356f333e564ab4790b6cb0df125b8e64e8d6474e73da49b1955/regex-2026.2.19-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:c1665138776e4ac1aa75146669236f7a8a696433ec4e525abf092ca9189247cc", size = 489541, upload-time = "2026-02-19T19:00:52.728Z" }, + { url = "https://files.pythonhosted.org/packages/15/77/fcc7bd9a67000d07fbcc11ed226077287a40d5c84544e62171d29d3ef59c/regex-2026.2.19-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d792b84709021945597e05656aac059526df4e0c9ef60a0eaebb306f8fafcaa8", size = 291414, upload-time = "2026-02-19T19:00:54.51Z" }, + { url = "https://files.pythonhosted.org/packages/f9/87/3997fc72dc59233426ef2e18dfdd105bb123812fff740ee9cc348f1a3243/regex-2026.2.19-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:db970bcce4d63b37b3f9eb8c893f0db980bbf1d404a1d8d2b17aa8189de92c53", size = 289140, upload-time = "2026-02-19T19:00:56.841Z" }, + { url = "https://files.pythonhosted.org/packages/f3/d0/b7dd3883ed1cff8ee0c0c9462d828aaf12be63bf5dc55453cbf423523b13/regex-2026.2.19-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:03d706fbe7dfec503c8c3cb76f9352b3e3b53b623672aa49f18a251a6c71b8e6", size = 798767, upload-time = "2026-02-19T19:00:59.014Z" }, + { url = "https://files.pythonhosted.org/packages/4a/7e/8e2d09103832891b2b735a2515abf377db21144c6dd5ede1fb03c619bf09/regex-2026.2.19-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8dbff048c042beef60aa1848961384572c5afb9e8b290b0f1203a5c42cf5af65", size = 864436, upload-time = "2026-02-19T19:01:00.772Z" }, + { url = "https://files.pythonhosted.org/packages/8a/2e/afea8d23a6db1f67f45e3a0da3057104ce32e154f57dd0c8997274d45fcd/regex-2026.2.19-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ccaaf9b907ea6b4223d5cbf5fa5dff5f33dc66f4907a25b967b8a81339a6e332", size = 912391, upload-time = "2026-02-19T19:01:02.865Z" }, + { url = "https://files.pythonhosted.org/packages/59/3c/ea5a4687adaba5e125b9bd6190153d0037325a0ba3757cc1537cc2c8dd90/regex-2026.2.19-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:75472631eee7898e16a8a20998d15106cb31cfde21cdf96ab40b432a7082af06", size = 803702, upload-time = "2026-02-19T19:01:05.298Z" }, + { url = "https://files.pythonhosted.org/packages/dc/c5/624a0705e8473a26488ec1a3a4e0b8763ecfc682a185c302dfec71daea35/regex-2026.2.19-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d89f85a5ccc0cec125c24be75610d433d65295827ebaf0d884cbe56df82d4774", size = 775980, upload-time = "2026-02-19T19:01:07.047Z" }, + { url = "https://files.pythonhosted.org/packages/4d/4b/ed776642533232b5599b7c1f9d817fe11faf597e8a92b7a44b841daaae76/regex-2026.2.19-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0d9f81806abdca3234c3dd582b8a97492e93de3602c8772013cb4affa12d1668", size = 788122, upload-time = "2026-02-19T19:01:08.744Z" }, + { url = "https://files.pythonhosted.org/packages/8c/58/e93e093921d13b9784b4f69896b6e2a9e09580a265c59d9eb95e87d288f2/regex-2026.2.19-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:9dadc10d1c2bbb1326e572a226d2ec56474ab8aab26fdb8cf19419b372c349a9", size = 858910, upload-time = "2026-02-19T19:01:10.488Z" }, + { url = "https://files.pythonhosted.org/packages/85/77/ff1d25a0c56cd546e0455cbc93235beb33474899690e6a361fa6b52d265b/regex-2026.2.19-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:6bc25d7e15f80c9dc7853cbb490b91c1ec7310808b09d56bd278fe03d776f4f6", size = 764153, upload-time = "2026-02-19T19:01:12.156Z" }, + { url = "https://files.pythonhosted.org/packages/cd/ef/8ec58df26d52d04443b1dc56f9be4b409f43ed5ae6c0248a287f52311fc4/regex-2026.2.19-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:965d59792f5037d9138da6fed50ba943162160443b43d4895b182551805aff9c", size = 850348, upload-time = "2026-02-19T19:01:14.147Z" }, + { url = "https://files.pythonhosted.org/packages/f5/b3/c42fd5ed91639ce5a4225b9df909180fc95586db071f2bf7c68d2ccbfbe6/regex-2026.2.19-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:38d88c6ed4a09ed61403dbdf515d969ccba34669af3961ceb7311ecd0cef504a", size = 789977, upload-time = "2026-02-19T19:01:15.838Z" }, + { url = "https://files.pythonhosted.org/packages/b6/22/bc3b58ebddbfd6ca5633e71fd41829ee931963aad1ebeec55aad0c23044e/regex-2026.2.19-cp312-cp312-win32.whl", hash = "sha256:5df947cabab4b643d4791af5e28aecf6bf62e6160e525651a12eba3d03755e6b", size = 266381, upload-time = "2026-02-19T19:01:17.952Z" }, + { url = "https://files.pythonhosted.org/packages/fc/4a/6ff550b63e67603ee60e69dc6bd2d5694e85046a558f663b2434bdaeb285/regex-2026.2.19-cp312-cp312-win_amd64.whl", hash = "sha256:4146dc576ea99634ae9c15587d0c43273b4023a10702998edf0fa68ccb60237a", size = 277274, upload-time = "2026-02-19T19:01:19.826Z" }, + { url = "https://files.pythonhosted.org/packages/cc/29/9ec48b679b1e87e7bc8517dff45351eab38f74fbbda1fbcf0e9e6d4e8174/regex-2026.2.19-cp312-cp312-win_arm64.whl", hash = "sha256:cdc0a80f679353bd68450d2a42996090c30b2e15ca90ded6156c31f1a3b63f3b", size = 270509, upload-time = "2026-02-19T19:01:22.075Z" }, + { url = "https://files.pythonhosted.org/packages/d2/2d/a849835e76ac88fcf9e8784e642d3ea635d183c4112150ca91499d6703af/regex-2026.2.19-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8df08decd339e8b3f6a2eb5c05c687fe9d963ae91f352bc57beb05f5b2ac6879", size = 489329, upload-time = "2026-02-19T19:01:23.841Z" }, + { url = "https://files.pythonhosted.org/packages/da/aa/78ff4666d3855490bae87845a5983485e765e1f970da20adffa2937b241d/regex-2026.2.19-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3aa0944f1dc6e92f91f3b306ba7f851e1009398c84bfd370633182ee4fc26a64", size = 291308, upload-time = "2026-02-19T19:01:25.605Z" }, + { url = "https://files.pythonhosted.org/packages/cd/58/714384efcc07ae6beba528a541f6e99188c5cc1bc0295337f4e8a868296d/regex-2026.2.19-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c13228fbecb03eadbfd8f521732c5fda09ef761af02e920a3148e18ad0e09968", size = 289033, upload-time = "2026-02-19T19:01:27.243Z" }, + { url = "https://files.pythonhosted.org/packages/75/ec/6438a9344d2869cf5265236a06af1ca6d885e5848b6561e10629bc8e5a11/regex-2026.2.19-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0d0e72703c60d68b18b27cde7cdb65ed2570ae29fb37231aa3076bfb6b1d1c13", size = 798798, upload-time = "2026-02-19T19:01:28.877Z" }, + { url = "https://files.pythonhosted.org/packages/c2/be/b1ce2d395e3fd2ce5f2fde2522f76cade4297cfe84cd61990ff48308749c/regex-2026.2.19-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:46e69a4bf552e30e74a8aa73f473c87efcb7f6e8c8ece60d9fd7bf13d5c86f02", size = 864444, upload-time = "2026-02-19T19:01:30.933Z" }, + { url = "https://files.pythonhosted.org/packages/d5/97/a3406460c504f7136f140d9461960c25f058b0240e4424d6fb73c7a067ab/regex-2026.2.19-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8edda06079bd770f7f0cf7f3bba1a0b447b96b4a543c91fe0c142d034c166161", size = 912633, upload-time = "2026-02-19T19:01:32.744Z" }, + { url = "https://files.pythonhosted.org/packages/8b/d9/e5dbef95008d84e9af1dc0faabbc34a7fbc8daa05bc5807c5cf86c2bec49/regex-2026.2.19-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9cbc69eae834afbf634f7c902fc72ff3e993f1c699156dd1af1adab5d06b7fe7", size = 803718, upload-time = "2026-02-19T19:01:34.61Z" }, + { url = "https://files.pythonhosted.org/packages/2f/e5/61d80132690a1ef8dc48e0f44248036877aebf94235d43f63a20d1598888/regex-2026.2.19-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bcf57d30659996ee5c7937999874504c11b5a068edc9515e6a59221cc2744dd1", size = 775975, upload-time = "2026-02-19T19:01:36.525Z" }, + { url = "https://files.pythonhosted.org/packages/05/32/ae828b3b312c972cf228b634447de27237d593d61505e6ad84723f8eabba/regex-2026.2.19-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:8e6e77cd92216eb489e21e5652a11b186afe9bdefca8a2db739fd6b205a9e0a4", size = 788129, upload-time = "2026-02-19T19:01:38.498Z" }, + { url = "https://files.pythonhosted.org/packages/cb/25/d74f34676f22bec401eddf0e5e457296941e10cbb2a49a571ca7a2c16e5a/regex-2026.2.19-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b9ab8dec42afefa6314ea9b31b188259ffdd93f433d77cad454cd0b8d235ce1c", size = 858818, upload-time = "2026-02-19T19:01:40.409Z" }, + { url = "https://files.pythonhosted.org/packages/1e/eb/0bc2b01a6b0b264e1406e5ef11cae3f634c3bd1a6e61206fd3227ce8e89c/regex-2026.2.19-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:294c0fb2e87c6bcc5f577c8f609210f5700b993151913352ed6c6af42f30f95f", size = 764186, upload-time = "2026-02-19T19:01:43.009Z" }, + { url = "https://files.pythonhosted.org/packages/eb/37/5fe5a630d0d99ecf0c3570f8905dafbc160443a2d80181607770086c9812/regex-2026.2.19-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:c0924c64b082d4512b923ac016d6e1dcf647a3560b8a4c7e55cbbd13656cb4ed", size = 850363, upload-time = "2026-02-19T19:01:45.015Z" }, + { url = "https://files.pythonhosted.org/packages/c3/45/ef68d805294b01ec030cfd388724ba76a5a21a67f32af05b17924520cb0b/regex-2026.2.19-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:790dbf87b0361606cb0d79b393c3e8f4436a14ee56568a7463014565d97da02a", size = 790026, upload-time = "2026-02-19T19:01:47.51Z" }, + { url = "https://files.pythonhosted.org/packages/d6/3a/40d3b66923dfc5aeba182f194f0ca35d09afe8c031a193e6ae46971a0a0e/regex-2026.2.19-cp313-cp313-win32.whl", hash = "sha256:43cdde87006271be6963896ed816733b10967baaf0e271d529c82e93da66675b", size = 266372, upload-time = "2026-02-19T19:01:49.469Z" }, + { url = "https://files.pythonhosted.org/packages/3d/f2/39082e8739bfd553497689e74f9d5e5bb531d6f8936d0b94f43e18f219c0/regex-2026.2.19-cp313-cp313-win_amd64.whl", hash = "sha256:127ea69273485348a126ebbf3d6052604d3c7da284f797bba781f364c0947d47", size = 277253, upload-time = "2026-02-19T19:01:51.208Z" }, + { url = "https://files.pythonhosted.org/packages/c2/c2/852b9600d53fb47e47080c203e2cdc0ac7e84e37032a57e0eaa37446033a/regex-2026.2.19-cp313-cp313-win_arm64.whl", hash = "sha256:5e56c669535ac59cbf96ca1ece0ef26cb66809990cda4fa45e1e32c3b146599e", size = 270505, upload-time = "2026-02-19T19:01:52.865Z" }, + { url = "https://files.pythonhosted.org/packages/a9/a2/e0b4575b93bc84db3b1fab24183e008691cd2db5c0ef14ed52681fbd94dd/regex-2026.2.19-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:93d881cab5afdc41a005dba1524a40947d6f7a525057aa64aaf16065cf62faa9", size = 492202, upload-time = "2026-02-19T19:01:54.816Z" }, + { url = "https://files.pythonhosted.org/packages/24/b5/b84fec8cbb5f92a7eed2b6b5353a6a9eed9670fee31817c2da9eb85dc797/regex-2026.2.19-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:80caaa1ddcc942ec7be18427354f9d58a79cee82dea2a6b3d4fd83302e1240d7", size = 292884, upload-time = "2026-02-19T19:01:58.254Z" }, + { url = "https://files.pythonhosted.org/packages/70/0c/fe89966dfae43da46f475362401f03e4d7dc3a3c955b54f632abc52669e0/regex-2026.2.19-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d793c5b4d2b4c668524cd1651404cfc798d40694c759aec997e196fe9729ec60", size = 291236, upload-time = "2026-02-19T19:01:59.966Z" }, + { url = "https://files.pythonhosted.org/packages/f2/f7/bda2695134f3e63eb5cccbbf608c2a12aab93d261ff4e2fe49b47fabc948/regex-2026.2.19-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5100acb20648d9efd3f4e7e91f51187f95f22a741dcd719548a6cf4e1b34b3f", size = 807660, upload-time = "2026-02-19T19:02:01.632Z" }, + { url = "https://files.pythonhosted.org/packages/11/56/6e3a4bf5e60d17326b7003d91bbde8938e439256dec211d835597a44972d/regex-2026.2.19-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5e3a31e94d10e52a896adaa3adf3621bd526ad2b45b8c2d23d1bbe74c7423007", size = 873585, upload-time = "2026-02-19T19:02:03.522Z" }, + { url = "https://files.pythonhosted.org/packages/35/5e/c90c6aa4d1317cc11839359479cfdd2662608f339e84e81ba751c8a4e461/regex-2026.2.19-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8497421099b981f67c99eba4154cf0dfd8e47159431427a11cfb6487f7791d9e", size = 915243, upload-time = "2026-02-19T19:02:05.608Z" }, + { url = "https://files.pythonhosted.org/packages/90/7c/981ea0694116793001496aaf9524e5c99e122ec3952d9e7f1878af3a6bf1/regex-2026.2.19-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1e7a08622f7d51d7a068f7e4052a38739c412a3e74f55817073d2e2418149619", size = 812922, upload-time = "2026-02-19T19:02:08.115Z" }, + { url = "https://files.pythonhosted.org/packages/2d/be/9eda82afa425370ffdb3fa9f3ea42450b9ae4da3ff0a4ec20466f69e371b/regex-2026.2.19-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8abe671cf0f15c26b1ad389bf4043b068ce7d3b1c5d9313e12895f57d6738555", size = 781318, upload-time = "2026-02-19T19:02:10.072Z" }, + { url = "https://files.pythonhosted.org/packages/c6/d5/50f0bbe56a8199f60a7b6c714e06e54b76b33d31806a69d0703b23ce2a9e/regex-2026.2.19-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5a8f28dd32a4ce9c41758d43b5b9115c1c497b4b1f50c457602c1d571fa98ce1", size = 795649, upload-time = "2026-02-19T19:02:11.96Z" }, + { url = "https://files.pythonhosted.org/packages/c5/09/d039f081e44a8b0134d0bb2dd805b0ddf390b69d0b58297ae098847c572f/regex-2026.2.19-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:654dc41a5ba9b8cc8432b3f1aa8906d8b45f3e9502442a07c2f27f6c63f85db5", size = 868844, upload-time = "2026-02-19T19:02:14.043Z" }, + { url = "https://files.pythonhosted.org/packages/ef/53/e2903b79a19ec8557fe7cd21cd093956ff2dbc2e0e33969e3adbe5b184dd/regex-2026.2.19-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:4a02faea614e7fdd6ba8b3bec6c8e79529d356b100381cec76e638f45d12ca04", size = 770113, upload-time = "2026-02-19T19:02:16.161Z" }, + { url = "https://files.pythonhosted.org/packages/8f/e2/784667767b55714ebb4e59bf106362327476b882c0b2f93c25e84cc99b1a/regex-2026.2.19-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:d96162140bb819814428800934c7b71b7bffe81fb6da2d6abc1dcca31741eca3", size = 854922, upload-time = "2026-02-19T19:02:18.155Z" }, + { url = "https://files.pythonhosted.org/packages/59/78/9ef4356bd4aed752775bd18071034979b85f035fec51f3a4f9dea497a254/regex-2026.2.19-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c227f2922153ee42bbeb355fd6d009f8c81d9d7bdd666e2276ce41f53ed9a743", size = 799636, upload-time = "2026-02-19T19:02:20.04Z" }, + { url = "https://files.pythonhosted.org/packages/cf/54/fcfc9287f20c5c9bd8db755aafe3e8cf4d99a6a3f1c7162ee182e0ca9374/regex-2026.2.19-cp313-cp313t-win32.whl", hash = "sha256:a178df8ec03011153fbcd2c70cb961bc98cbbd9694b28f706c318bee8927c3db", size = 268968, upload-time = "2026-02-19T19:02:22.816Z" }, + { url = "https://files.pythonhosted.org/packages/1e/a0/ff24c6cb1273e42472706d277147fc38e1f9074a280fb6034b0fc9b69415/regex-2026.2.19-cp313-cp313t-win_amd64.whl", hash = "sha256:2c1693ca6f444d554aa246b592355b5cec030ace5a2729eae1b04ab6e853e768", size = 280390, upload-time = "2026-02-19T19:02:25.231Z" }, + { url = "https://files.pythonhosted.org/packages/1a/b6/a3f6ad89d780ffdeebb4d5e2e3e30bd2ef1f70f6a94d1760e03dd1e12c60/regex-2026.2.19-cp313-cp313t-win_arm64.whl", hash = "sha256:c0761d7ae8d65773e01515ebb0b304df1bf37a0a79546caad9cbe79a42c12af7", size = 271643, upload-time = "2026-02-19T19:02:27.175Z" }, { url = "https://files.pythonhosted.org/packages/2d/e2/7ad4e76a6dddefc0d64dbe12a4d3ca3947a19ddc501f864a5df2a8222ddd/regex-2026.2.19-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:03d191a9bcf94d31af56d2575210cb0d0c6a054dbcad2ea9e00aa4c42903b919", size = 489306, upload-time = "2026-02-19T19:02:29.058Z" }, { url = "https://files.pythonhosted.org/packages/14/95/ee1736135733afbcf1846c58671046f99c4d5170102a150ebb3dd8d701d9/regex-2026.2.19-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:516ee067c6c721d0d0bfb80a2004edbd060fffd07e456d4e1669e38fe82f922e", size = 291218, upload-time = "2026-02-19T19:02:31.083Z" }, { url = "https://files.pythonhosted.org/packages/ef/08/180d1826c3d7065200a5168c6b993a44947395c7bb6e04b2c2a219c34225/regex-2026.2.19-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:997862c619994c4a356cb7c3592502cbd50c2ab98da5f61c5c871f10f22de7e5", size = 289097, upload-time = "2026-02-19T19:02:33.485Z" }, @@ -1668,6 +2214,50 @@ version = "0.30.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/20/af/3f2f423103f1113b36230496629986e0ef7e199d2aa8392452b484b38ced/rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84", size = 69469, upload-time = "2025-11-30T20:24:38.837Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/03/e7/98a2f4ac921d82f33e03f3835f5bf3a4a40aa1bfdc57975e74a97b2b4bdd/rpds_py-0.30.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a161f20d9a43006833cd7068375a94d035714d73a172b681d8881820600abfad", size = 375086, upload-time = "2025-11-30T20:22:17.93Z" }, + { url = "https://files.pythonhosted.org/packages/4d/a1/bca7fd3d452b272e13335db8d6b0b3ecde0f90ad6f16f3328c6fb150c889/rpds_py-0.30.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6abc8880d9d036ecaafe709079969f56e876fcf107f7a8e9920ba6d5a3878d05", size = 359053, upload-time = "2025-11-30T20:22:19.297Z" }, + { url = "https://files.pythonhosted.org/packages/65/1c/ae157e83a6357eceff62ba7e52113e3ec4834a84cfe07fa4b0757a7d105f/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca28829ae5f5d569bb62a79512c842a03a12576375d5ece7d2cadf8abe96ec28", size = 390763, upload-time = "2025-11-30T20:22:21.661Z" }, + { url = "https://files.pythonhosted.org/packages/d4/36/eb2eb8515e2ad24c0bd43c3ee9cd74c33f7ca6430755ccdb240fd3144c44/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a1010ed9524c73b94d15919ca4d41d8780980e1765babf85f9a2f90d247153dd", size = 408951, upload-time = "2025-11-30T20:22:23.408Z" }, + { url = "https://files.pythonhosted.org/packages/d6/65/ad8dc1784a331fabbd740ef6f71ce2198c7ed0890dab595adb9ea2d775a1/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f8d1736cfb49381ba528cd5baa46f82fdc65c06e843dab24dd70b63d09121b3f", size = 514622, upload-time = "2025-11-30T20:22:25.16Z" }, + { url = "https://files.pythonhosted.org/packages/63/8e/0cfa7ae158e15e143fe03993b5bcd743a59f541f5952e1546b1ac1b5fd45/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d948b135c4693daff7bc2dcfc4ec57237a29bd37e60c2fabf5aff2bbacf3e2f1", size = 414492, upload-time = "2025-11-30T20:22:26.505Z" }, + { url = "https://files.pythonhosted.org/packages/60/1b/6f8f29f3f995c7ffdde46a626ddccd7c63aefc0efae881dc13b6e5d5bb16/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47f236970bccb2233267d89173d3ad2703cd36a0e2a6e92d0560d333871a3d23", size = 394080, upload-time = "2025-11-30T20:22:27.934Z" }, + { url = "https://files.pythonhosted.org/packages/6d/d5/a266341051a7a3ca2f4b750a3aa4abc986378431fc2da508c5034d081b70/rpds_py-0.30.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:2e6ecb5a5bcacf59c3f912155044479af1d0b6681280048b338b28e364aca1f6", size = 408680, upload-time = "2025-11-30T20:22:29.341Z" }, + { url = "https://files.pythonhosted.org/packages/10/3b/71b725851df9ab7a7a4e33cf36d241933da66040d195a84781f49c50490c/rpds_py-0.30.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a8fa71a2e078c527c3e9dc9fc5a98c9db40bcc8a92b4e8858e36d329f8684b51", size = 423589, upload-time = "2025-11-30T20:22:31.469Z" }, + { url = "https://files.pythonhosted.org/packages/00/2b/e59e58c544dc9bd8bd8384ecdb8ea91f6727f0e37a7131baeff8d6f51661/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:73c67f2db7bc334e518d097c6d1e6fed021bbc9b7d678d6cc433478365d1d5f5", size = 573289, upload-time = "2025-11-30T20:22:32.997Z" }, + { url = "https://files.pythonhosted.org/packages/da/3e/a18e6f5b460893172a7d6a680e86d3b6bc87a54c1f0b03446a3c8c7b588f/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5ba103fb455be00f3b1c2076c9d4264bfcb037c976167a6047ed82f23153f02e", size = 599737, upload-time = "2025-11-30T20:22:34.419Z" }, + { url = "https://files.pythonhosted.org/packages/5c/e2/714694e4b87b85a18e2c243614974413c60aa107fd815b8cbc42b873d1d7/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7cee9c752c0364588353e627da8a7e808a66873672bcb5f52890c33fd965b394", size = 563120, upload-time = "2025-11-30T20:22:35.903Z" }, + { url = "https://files.pythonhosted.org/packages/6f/ab/d5d5e3bcedb0a77f4f613706b750e50a5a3ba1c15ccd3665ecc636c968fd/rpds_py-0.30.0-cp312-cp312-win32.whl", hash = "sha256:1ab5b83dbcf55acc8b08fc62b796ef672c457b17dbd7820a11d6c52c06839bdf", size = 223782, upload-time = "2025-11-30T20:22:37.271Z" }, + { url = "https://files.pythonhosted.org/packages/39/3b/f786af9957306fdc38a74cef405b7b93180f481fb48453a114bb6465744a/rpds_py-0.30.0-cp312-cp312-win_amd64.whl", hash = "sha256:a090322ca841abd453d43456ac34db46e8b05fd9b3b4ac0c78bcde8b089f959b", size = 240463, upload-time = "2025-11-30T20:22:39.021Z" }, + { url = "https://files.pythonhosted.org/packages/f3/d2/b91dc748126c1559042cfe41990deb92c4ee3e2b415f6b5234969ffaf0cc/rpds_py-0.30.0-cp312-cp312-win_arm64.whl", hash = "sha256:669b1805bd639dd2989b281be2cfd951c6121b65e729d9b843e9639ef1fd555e", size = 230868, upload-time = "2025-11-30T20:22:40.493Z" }, + { url = "https://files.pythonhosted.org/packages/ed/dc/d61221eb88ff410de3c49143407f6f3147acf2538c86f2ab7ce65ae7d5f9/rpds_py-0.30.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f83424d738204d9770830d35290ff3273fbb02b41f919870479fab14b9d303b2", size = 374887, upload-time = "2025-11-30T20:22:41.812Z" }, + { url = "https://files.pythonhosted.org/packages/fd/32/55fb50ae104061dbc564ef15cc43c013dc4a9f4527a1f4d99baddf56fe5f/rpds_py-0.30.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e7536cd91353c5273434b4e003cbda89034d67e7710eab8761fd918ec6c69cf8", size = 358904, upload-time = "2025-11-30T20:22:43.479Z" }, + { url = "https://files.pythonhosted.org/packages/58/70/faed8186300e3b9bdd138d0273109784eea2396c68458ed580f885dfe7ad/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2771c6c15973347f50fece41fc447c054b7ac2ae0502388ce3b6738cd366e3d4", size = 389945, upload-time = "2025-11-30T20:22:44.819Z" }, + { url = "https://files.pythonhosted.org/packages/bd/a8/073cac3ed2c6387df38f71296d002ab43496a96b92c823e76f46b8af0543/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0a59119fc6e3f460315fe9d08149f8102aa322299deaa5cab5b40092345c2136", size = 407783, upload-time = "2025-11-30T20:22:46.103Z" }, + { url = "https://files.pythonhosted.org/packages/77/57/5999eb8c58671f1c11eba084115e77a8899d6e694d2a18f69f0ba471ec8b/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76fec018282b4ead0364022e3c54b60bf368b9d926877957a8624b58419169b7", size = 515021, upload-time = "2025-11-30T20:22:47.458Z" }, + { url = "https://files.pythonhosted.org/packages/e0/af/5ab4833eadc36c0a8ed2bc5c0de0493c04f6c06de223170bd0798ff98ced/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:692bef75a5525db97318e8cd061542b5a79812d711ea03dbc1f6f8dbb0c5f0d2", size = 414589, upload-time = "2025-11-30T20:22:48.872Z" }, + { url = "https://files.pythonhosted.org/packages/b7/de/f7192e12b21b9e9a68a6d0f249b4af3fdcdff8418be0767a627564afa1f1/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9027da1ce107104c50c81383cae773ef5c24d296dd11c99e2629dbd7967a20c6", size = 394025, upload-time = "2025-11-30T20:22:50.196Z" }, + { url = "https://files.pythonhosted.org/packages/91/c4/fc70cd0249496493500e7cc2de87504f5aa6509de1e88623431fec76d4b6/rpds_py-0.30.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:9cf69cdda1f5968a30a359aba2f7f9aa648a9ce4b580d6826437f2b291cfc86e", size = 408895, upload-time = "2025-11-30T20:22:51.87Z" }, + { url = "https://files.pythonhosted.org/packages/58/95/d9275b05ab96556fefff73a385813eb66032e4c99f411d0795372d9abcea/rpds_py-0.30.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a4796a717bf12b9da9d3ad002519a86063dcac8988b030e405704ef7d74d2d9d", size = 422799, upload-time = "2025-11-30T20:22:53.341Z" }, + { url = "https://files.pythonhosted.org/packages/06/c1/3088fc04b6624eb12a57eb814f0d4997a44b0d208d6cace713033ff1a6ba/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5d4c2aa7c50ad4728a094ebd5eb46c452e9cb7edbfdb18f9e1221f597a73e1e7", size = 572731, upload-time = "2025-11-30T20:22:54.778Z" }, + { url = "https://files.pythonhosted.org/packages/d8/42/c612a833183b39774e8ac8fecae81263a68b9583ee343db33ab571a7ce55/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ba81a9203d07805435eb06f536d95a266c21e5b2dfbf6517748ca40c98d19e31", size = 599027, upload-time = "2025-11-30T20:22:56.212Z" }, + { url = "https://files.pythonhosted.org/packages/5f/60/525a50f45b01d70005403ae0e25f43c0384369ad24ffe46e8d9068b50086/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:945dccface01af02675628334f7cf49c2af4c1c904748efc5cf7bbdf0b579f95", size = 563020, upload-time = "2025-11-30T20:22:58.2Z" }, + { url = "https://files.pythonhosted.org/packages/0b/5d/47c4655e9bcd5ca907148535c10e7d489044243cc9941c16ed7cd53be91d/rpds_py-0.30.0-cp313-cp313-win32.whl", hash = "sha256:b40fb160a2db369a194cb27943582b38f79fc4887291417685f3ad693c5a1d5d", size = 223139, upload-time = "2025-11-30T20:23:00.209Z" }, + { url = "https://files.pythonhosted.org/packages/f2/e1/485132437d20aa4d3e1d8b3fb5a5e65aa8139f1e097080c2a8443201742c/rpds_py-0.30.0-cp313-cp313-win_amd64.whl", hash = "sha256:806f36b1b605e2d6a72716f321f20036b9489d29c51c91f4dd29a3e3afb73b15", size = 240224, upload-time = "2025-11-30T20:23:02.008Z" }, + { url = "https://files.pythonhosted.org/packages/24/95/ffd128ed1146a153d928617b0ef673960130be0009c77d8fbf0abe306713/rpds_py-0.30.0-cp313-cp313-win_arm64.whl", hash = "sha256:d96c2086587c7c30d44f31f42eae4eac89b60dabbac18c7669be3700f13c3ce1", size = 230645, upload-time = "2025-11-30T20:23:03.43Z" }, + { url = "https://files.pythonhosted.org/packages/ff/1b/b10de890a0def2a319a2626334a7f0ae388215eb60914dbac8a3bae54435/rpds_py-0.30.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:eb0b93f2e5c2189ee831ee43f156ed34e2a89a78a66b98cadad955972548be5a", size = 364443, upload-time = "2025-11-30T20:23:04.878Z" }, + { url = "https://files.pythonhosted.org/packages/0d/bf/27e39f5971dc4f305a4fb9c672ca06f290f7c4e261c568f3dea16a410d47/rpds_py-0.30.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:922e10f31f303c7c920da8981051ff6d8c1a56207dbdf330d9047f6d30b70e5e", size = 353375, upload-time = "2025-11-30T20:23:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/40/58/442ada3bba6e8e6615fc00483135c14a7538d2ffac30e2d933ccf6852232/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdc62c8286ba9bf7f47befdcea13ea0e26bf294bda99758fd90535cbaf408000", size = 383850, upload-time = "2025-11-30T20:23:07.825Z" }, + { url = "https://files.pythonhosted.org/packages/14/14/f59b0127409a33c6ef6f5c1ebd5ad8e32d7861c9c7adfa9a624fc3889f6c/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47f9a91efc418b54fb8190a6b4aa7813a23fb79c51f4bb84e418f5476c38b8db", size = 392812, upload-time = "2025-11-30T20:23:09.228Z" }, + { url = "https://files.pythonhosted.org/packages/b3/66/e0be3e162ac299b3a22527e8913767d869e6cc75c46bd844aa43fb81ab62/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3587eb9b17f3789ad50824084fa6f81921bbf9a795826570bda82cb3ed91f2", size = 517841, upload-time = "2025-11-30T20:23:11.186Z" }, + { url = "https://files.pythonhosted.org/packages/3d/55/fa3b9cf31d0c963ecf1ba777f7cf4b2a2c976795ac430d24a1f43d25a6ba/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39c02563fc592411c2c61d26b6c5fe1e51eaa44a75aa2c8735ca88b0d9599daa", size = 408149, upload-time = "2025-11-30T20:23:12.864Z" }, + { url = "https://files.pythonhosted.org/packages/60/ca/780cf3b1a32b18c0f05c441958d3758f02544f1d613abf9488cd78876378/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51a1234d8febafdfd33a42d97da7a43f5dcb120c1060e352a3fbc0c6d36e2083", size = 383843, upload-time = "2025-11-30T20:23:14.638Z" }, + { url = "https://files.pythonhosted.org/packages/82/86/d5f2e04f2aa6247c613da0c1dd87fcd08fa17107e858193566048a1e2f0a/rpds_py-0.30.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:eb2c4071ab598733724c08221091e8d80e89064cd472819285a9ab0f24bcedb9", size = 396507, upload-time = "2025-11-30T20:23:16.105Z" }, + { url = "https://files.pythonhosted.org/packages/4b/9a/453255d2f769fe44e07ea9785c8347edaf867f7026872e76c1ad9f7bed92/rpds_py-0.30.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6bdfdb946967d816e6adf9a3d8201bfad269c67efe6cefd7093ef959683c8de0", size = 414949, upload-time = "2025-11-30T20:23:17.539Z" }, + { url = "https://files.pythonhosted.org/packages/a3/31/622a86cdc0c45d6df0e9ccb6becdba5074735e7033c20e401a6d9d0e2ca0/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c77afbd5f5250bf27bf516c7c4a016813eb2d3e116139aed0096940c5982da94", size = 565790, upload-time = "2025-11-30T20:23:19.029Z" }, + { url = "https://files.pythonhosted.org/packages/1c/5d/15bbf0fb4a3f58a3b1c67855ec1efcc4ceaef4e86644665fff03e1b66d8d/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:61046904275472a76c8c90c9ccee9013d70a6d0f73eecefd38c1ae7c39045a08", size = 590217, upload-time = "2025-11-30T20:23:20.885Z" }, + { url = "https://files.pythonhosted.org/packages/6d/61/21b8c41f68e60c8cc3b2e25644f0e3681926020f11d06ab0b78e3c6bbff1/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c5f36a861bc4b7da6516dbdf302c55313afa09b81931e8280361a4f6c9a2d27", size = 555806, upload-time = "2025-11-30T20:23:22.488Z" }, + { url = "https://files.pythonhosted.org/packages/f9/39/7e067bb06c31de48de3eb200f9fc7c58982a4d3db44b07e73963e10d3be9/rpds_py-0.30.0-cp313-cp313t-win32.whl", hash = "sha256:3d4a69de7a3e50ffc214ae16d79d8fbb0922972da0356dcf4d0fdca2878559c6", size = 211341, upload-time = "2025-11-30T20:23:24.449Z" }, + { url = "https://files.pythonhosted.org/packages/0a/4d/222ef0b46443cf4cf46764d9c630f3fe4abaa7245be9417e56e9f52b8f65/rpds_py-0.30.0-cp313-cp313t-win_amd64.whl", hash = "sha256:f14fc5df50a716f7ece6a80b6c78bb35ea2ca47c499e422aa4463455dd96d56d", size = 225768, upload-time = "2025-11-30T20:23:25.908Z" }, { url = "https://files.pythonhosted.org/packages/86/81/dad16382ebbd3d0e0328776d8fd7ca94220e4fa0798d1dc5e7da48cb3201/rpds_py-0.30.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:68f19c879420aa08f61203801423f6cd5ac5f0ac4ac82a2368a9fcd6a9a075e0", size = 362099, upload-time = "2025-11-30T20:23:27.316Z" }, { url = "https://files.pythonhosted.org/packages/2b/60/19f7884db5d5603edf3c6bce35408f45ad3e97e10007df0e17dd57af18f8/rpds_py-0.30.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ec7c4490c672c1a0389d319b3a9cfcd098dcdc4783991553c332a15acf7249be", size = 353192, upload-time = "2025-11-30T20:23:29.151Z" }, { url = "https://files.pythonhosted.org/packages/bf/c4/76eb0e1e72d1a9c4703c69607cec123c29028bff28ce41588792417098ac/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f251c812357a3fed308d684a5079ddfb9d933860fc6de89f2b7ab00da481e65f", size = 384080, upload-time = "2025-11-30T20:23:30.785Z" }, @@ -1767,6 +2357,7 @@ version = "0.52.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/c4/68/79977123bb7be889ad680d79a40f339082c1978b5cfcf62c2d8d196873ac/starlette-0.52.1.tar.gz", hash = "sha256:834edd1b0a23167694292e94f597773bc3f89f362be6effee198165a35d62933", size = 2653702, upload-time = "2026-01-18T13:34:11.062Z" } wheels = [ @@ -1783,6 +2374,27 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/7d/ab/4d017d0f76ec3171d469d80fc03dfbb4e48a4bcaddaa831b31d526f05edc/tiktoken-0.12.0.tar.gz", hash = "sha256:b18ba7ee2b093863978fcb14f74b3707cdc8d4d4d3836853ce7ec60772139931", size = 37806, upload-time = "2025-10-06T20:22:45.419Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/a4/85/be65d39d6b647c79800fd9d29241d081d4eeb06271f383bb87200d74cf76/tiktoken-0.12.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b97f74aca0d78a1ff21b8cd9e9925714c15a9236d6ceacf5c7327c117e6e21e8", size = 1050728, upload-time = "2025-10-06T20:21:52.756Z" }, + { url = "https://files.pythonhosted.org/packages/4a/42/6573e9129bc55c9bf7300b3a35bef2c6b9117018acca0dc760ac2d93dffe/tiktoken-0.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2b90f5ad190a4bb7c3eb30c5fa32e1e182ca1ca79f05e49b448438c3e225a49b", size = 994049, upload-time = "2025-10-06T20:21:53.782Z" }, + { url = "https://files.pythonhosted.org/packages/66/c5/ed88504d2f4a5fd6856990b230b56d85a777feab84e6129af0822f5d0f70/tiktoken-0.12.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:65b26c7a780e2139e73acc193e5c63ac754021f160df919add909c1492c0fb37", size = 1129008, upload-time = "2025-10-06T20:21:54.832Z" }, + { url = "https://files.pythonhosted.org/packages/f4/90/3dae6cc5436137ebd38944d396b5849e167896fc2073da643a49f372dc4f/tiktoken-0.12.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:edde1ec917dfd21c1f2f8046b86348b0f54a2c0547f68149d8600859598769ad", size = 1152665, upload-time = "2025-10-06T20:21:56.129Z" }, + { url = "https://files.pythonhosted.org/packages/a3/fe/26df24ce53ffde419a42f5f53d755b995c9318908288c17ec3f3448313a3/tiktoken-0.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:35a2f8ddd3824608b3d650a000c1ef71f730d0c56486845705a8248da00f9fe5", size = 1194230, upload-time = "2025-10-06T20:21:57.546Z" }, + { url = "https://files.pythonhosted.org/packages/20/cc/b064cae1a0e9fac84b0d2c46b89f4e57051a5f41324e385d10225a984c24/tiktoken-0.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:83d16643edb7fa2c99eff2ab7733508aae1eebb03d5dfc46f5565862810f24e3", size = 1254688, upload-time = "2025-10-06T20:21:58.619Z" }, + { url = "https://files.pythonhosted.org/packages/81/10/b8523105c590c5b8349f2587e2fdfe51a69544bd5a76295fc20f2374f470/tiktoken-0.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ffc5288f34a8bc02e1ea7047b8d041104791d2ddbf42d1e5fa07822cbffe16bd", size = 878694, upload-time = "2025-10-06T20:21:59.876Z" }, + { url = "https://files.pythonhosted.org/packages/00/61/441588ee21e6b5cdf59d6870f86beb9789e532ee9718c251b391b70c68d6/tiktoken-0.12.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:775c2c55de2310cc1bc9a3ad8826761cbdc87770e586fd7b6da7d4589e13dab3", size = 1050802, upload-time = "2025-10-06T20:22:00.96Z" }, + { url = "https://files.pythonhosted.org/packages/1f/05/dcf94486d5c5c8d34496abe271ac76c5b785507c8eae71b3708f1ad9b45a/tiktoken-0.12.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a01b12f69052fbe4b080a2cfb867c4de12c704b56178edf1d1d7b273561db160", size = 993995, upload-time = "2025-10-06T20:22:02.788Z" }, + { url = "https://files.pythonhosted.org/packages/a0/70/5163fe5359b943f8db9946b62f19be2305de8c3d78a16f629d4165e2f40e/tiktoken-0.12.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:01d99484dc93b129cd0964f9d34eee953f2737301f18b3c7257bf368d7615baa", size = 1128948, upload-time = "2025-10-06T20:22:03.814Z" }, + { url = "https://files.pythonhosted.org/packages/0c/da/c028aa0babf77315e1cef357d4d768800c5f8a6de04d0eac0f377cb619fa/tiktoken-0.12.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:4a1a4fcd021f022bfc81904a911d3df0f6543b9e7627b51411da75ff2fe7a1be", size = 1151986, upload-time = "2025-10-06T20:22:05.173Z" }, + { url = "https://files.pythonhosted.org/packages/a0/5a/886b108b766aa53e295f7216b509be95eb7d60b166049ce2c58416b25f2a/tiktoken-0.12.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:981a81e39812d57031efdc9ec59fa32b2a5a5524d20d4776574c4b4bd2e9014a", size = 1194222, upload-time = "2025-10-06T20:22:06.265Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f8/4db272048397636ac7a078d22773dd2795b1becee7bc4922fe6207288d57/tiktoken-0.12.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9baf52f84a3f42eef3ff4e754a0db79a13a27921b457ca9832cf944c6be4f8f3", size = 1255097, upload-time = "2025-10-06T20:22:07.403Z" }, + { url = "https://files.pythonhosted.org/packages/8e/32/45d02e2e0ea2be3a9ed22afc47d93741247e75018aac967b713b2941f8ea/tiktoken-0.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:b8a0cd0c789a61f31bf44851defbd609e8dd1e2c8589c614cc1060940ef1f697", size = 879117, upload-time = "2025-10-06T20:22:08.418Z" }, + { url = "https://files.pythonhosted.org/packages/ce/76/994fc868f88e016e6d05b0da5ac24582a14c47893f4474c3e9744283f1d5/tiktoken-0.12.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d5f89ea5680066b68bcb797ae85219c72916c922ef0fcdd3480c7d2315ffff16", size = 1050309, upload-time = "2025-10-06T20:22:10.939Z" }, + { url = "https://files.pythonhosted.org/packages/f6/b8/57ef1456504c43a849821920d582a738a461b76a047f352f18c0b26c6516/tiktoken-0.12.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b4e7ed1c6a7a8a60a3230965bdedba8cc58f68926b835e519341413370e0399a", size = 993712, upload-time = "2025-10-06T20:22:12.115Z" }, + { url = "https://files.pythonhosted.org/packages/72/90/13da56f664286ffbae9dbcfadcc625439142675845baa62715e49b87b68b/tiktoken-0.12.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:fc530a28591a2d74bce821d10b418b26a094bf33839e69042a6e86ddb7a7fb27", size = 1128725, upload-time = "2025-10-06T20:22:13.541Z" }, + { url = "https://files.pythonhosted.org/packages/05/df/4f80030d44682235bdaecd7346c90f67ae87ec8f3df4a3442cb53834f7e4/tiktoken-0.12.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:06a9f4f49884139013b138920a4c393aa6556b2f8f536345f11819389c703ebb", size = 1151875, upload-time = "2025-10-06T20:22:14.559Z" }, + { url = "https://files.pythonhosted.org/packages/22/1f/ae535223a8c4ef4c0c1192e3f9b82da660be9eb66b9279e95c99288e9dab/tiktoken-0.12.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:04f0e6a985d95913cabc96a741c5ffec525a2c72e9df086ff17ebe35985c800e", size = 1194451, upload-time = "2025-10-06T20:22:15.545Z" }, + { url = "https://files.pythonhosted.org/packages/78/a7/f8ead382fce0243cb625c4f266e66c27f65ae65ee9e77f59ea1653b6d730/tiktoken-0.12.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0ee8f9ae00c41770b5f9b0bb1235474768884ae157de3beb5439ca0fd70f3e25", size = 1253794, upload-time = "2025-10-06T20:22:16.624Z" }, + { url = "https://files.pythonhosted.org/packages/93/e0/6cc82a562bc6365785a3ff0af27a2a092d57c47d7a81d9e2295d8c36f011/tiktoken-0.12.0-cp313-cp313t-win_amd64.whl", hash = "sha256:dc2dd125a62cb2b3d858484d6c614d136b5b848976794edfb63688d539b8b93f", size = 878777, upload-time = "2025-10-06T20:22:18.036Z" }, { url = "https://files.pythonhosted.org/packages/72/05/3abc1db5d2c9aadc4d2c76fa5640134e475e58d9fbb82b5c535dc0de9b01/tiktoken-0.12.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:a90388128df3b3abeb2bfd1895b0681412a8d7dc644142519e6f0a97c2111646", size = 1050188, upload-time = "2025-10-06T20:22:19.563Z" }, { url = "https://files.pythonhosted.org/packages/e3/7b/50c2f060412202d6c95f32b20755c7a6273543b125c0985d6fa9465105af/tiktoken-0.12.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:da900aa0ad52247d8794e307d6446bd3cdea8e192769b56276695d34d2c9aa88", size = 993978, upload-time = "2025-10-06T20:22:20.702Z" }, { url = "https://files.pythonhosted.org/packages/14/27/bf795595a2b897e271771cd31cb847d479073497344c637966bdf2853da1/tiktoken-0.12.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:285ba9d73ea0d6171e7f9407039a290ca77efcdb026be7769dccc01d2c8d7fff", size = 1129271, upload-time = "2025-10-06T20:22:22.06Z" }, @@ -1922,6 +2534,24 @@ version = "16.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/04/24/4b2031d72e840ce4c1ccb255f693b15c334757fc50023e4db9537080b8c4/websockets-16.0.tar.gz", hash = "sha256:5f6261a5e56e8d5c42a4497b364ea24d94d9563e8fbd44e78ac40879c60179b5", size = 179346, upload-time = "2026-01-10T09:23:47.181Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/84/7b/bac442e6b96c9d25092695578dda82403c77936104b5682307bd4deb1ad4/websockets-16.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:71c989cbf3254fbd5e84d3bff31e4da39c43f884e64f2551d14bb3c186230f00", size = 177365, upload-time = "2026-01-10T09:22:46.787Z" }, + { url = "https://files.pythonhosted.org/packages/b0/fe/136ccece61bd690d9c1f715baaeefd953bb2360134de73519d5df19d29ca/websockets-16.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8b6e209ffee39ff1b6d0fa7bfef6de950c60dfb91b8fcead17da4ee539121a79", size = 175038, upload-time = "2026-01-10T09:22:47.999Z" }, + { url = "https://files.pythonhosted.org/packages/40/1e/9771421ac2286eaab95b8575b0cb701ae3663abf8b5e1f64f1fd90d0a673/websockets-16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:86890e837d61574c92a97496d590968b23c2ef0aeb8a9bc9421d174cd378ae39", size = 175328, upload-time = "2026-01-10T09:22:49.809Z" }, + { url = "https://files.pythonhosted.org/packages/18/29/71729b4671f21e1eaa5d6573031ab810ad2936c8175f03f97f3ff164c802/websockets-16.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9b5aca38b67492ef518a8ab76851862488a478602229112c4b0d58d63a7a4d5c", size = 184915, upload-time = "2026-01-10T09:22:51.071Z" }, + { url = "https://files.pythonhosted.org/packages/97/bb/21c36b7dbbafc85d2d480cd65df02a1dc93bf76d97147605a8e27ff9409d/websockets-16.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e0334872c0a37b606418ac52f6ab9cfd17317ac26365f7f65e203e2d0d0d359f", size = 186152, upload-time = "2026-01-10T09:22:52.224Z" }, + { url = "https://files.pythonhosted.org/packages/4a/34/9bf8df0c0cf88fa7bfe36678dc7b02970c9a7d5e065a3099292db87b1be2/websockets-16.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a0b31e0b424cc6b5a04b8838bbaec1688834b2383256688cf47eb97412531da1", size = 185583, upload-time = "2026-01-10T09:22:53.443Z" }, + { url = "https://files.pythonhosted.org/packages/47/88/4dd516068e1a3d6ab3c7c183288404cd424a9a02d585efbac226cb61ff2d/websockets-16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:485c49116d0af10ac698623c513c1cc01c9446c058a4e61e3bf6c19dff7335a2", size = 184880, upload-time = "2026-01-10T09:22:55.033Z" }, + { url = "https://files.pythonhosted.org/packages/91/d6/7d4553ad4bf1c0421e1ebd4b18de5d9098383b5caa1d937b63df8d04b565/websockets-16.0-cp312-cp312-win32.whl", hash = "sha256:eaded469f5e5b7294e2bdca0ab06becb6756ea86894a47806456089298813c89", size = 178261, upload-time = "2026-01-10T09:22:56.251Z" }, + { url = "https://files.pythonhosted.org/packages/c3/f0/f3a17365441ed1c27f850a80b2bc680a0fa9505d733fe152fdf5e98c1c0b/websockets-16.0-cp312-cp312-win_amd64.whl", hash = "sha256:5569417dc80977fc8c2d43a86f78e0a5a22fee17565d78621b6bb264a115d4ea", size = 178693, upload-time = "2026-01-10T09:22:57.478Z" }, + { url = "https://files.pythonhosted.org/packages/cc/9c/baa8456050d1c1b08dd0ec7346026668cbc6f145ab4e314d707bb845bf0d/websockets-16.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:878b336ac47938b474c8f982ac2f7266a540adc3fa4ad74ae96fea9823a02cc9", size = 177364, upload-time = "2026-01-10T09:22:59.333Z" }, + { url = "https://files.pythonhosted.org/packages/7e/0c/8811fc53e9bcff68fe7de2bcbe75116a8d959ac699a3200f4847a8925210/websockets-16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:52a0fec0e6c8d9a784c2c78276a48a2bdf099e4ccc2a4cad53b27718dbfd0230", size = 175039, upload-time = "2026-01-10T09:23:01.171Z" }, + { url = "https://files.pythonhosted.org/packages/aa/82/39a5f910cb99ec0b59e482971238c845af9220d3ab9fa76dd9162cda9d62/websockets-16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e6578ed5b6981005df1860a56e3617f14a6c307e6a71b4fff8c48fdc50f3ed2c", size = 175323, upload-time = "2026-01-10T09:23:02.341Z" }, + { url = "https://files.pythonhosted.org/packages/bd/28/0a25ee5342eb5d5f297d992a77e56892ecb65e7854c7898fb7d35e9b33bd/websockets-16.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:95724e638f0f9c350bb1c2b0a7ad0e83d9cc0c9259f3ea94e40d7b02a2179ae5", size = 184975, upload-time = "2026-01-10T09:23:03.756Z" }, + { url = "https://files.pythonhosted.org/packages/f9/66/27ea52741752f5107c2e41fda05e8395a682a1e11c4e592a809a90c6a506/websockets-16.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0204dc62a89dc9d50d682412c10b3542d748260d743500a85c13cd1ee4bde82", size = 186203, upload-time = "2026-01-10T09:23:05.01Z" }, + { url = "https://files.pythonhosted.org/packages/37/e5/8e32857371406a757816a2b471939d51c463509be73fa538216ea52b792a/websockets-16.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:52ac480f44d32970d66763115edea932f1c5b1312de36df06d6b219f6741eed8", size = 185653, upload-time = "2026-01-10T09:23:06.301Z" }, + { url = "https://files.pythonhosted.org/packages/9b/67/f926bac29882894669368dc73f4da900fcdf47955d0a0185d60103df5737/websockets-16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6e5a82b677f8f6f59e8dfc34ec06ca6b5b48bc4fcda346acd093694cc2c24d8f", size = 184920, upload-time = "2026-01-10T09:23:07.492Z" }, + { url = "https://files.pythonhosted.org/packages/3c/a1/3d6ccdcd125b0a42a311bcd15a7f705d688f73b2a22d8cf1c0875d35d34a/websockets-16.0-cp313-cp313-win32.whl", hash = "sha256:abf050a199613f64c886ea10f38b47770a65154dc37181bfaff70c160f45315a", size = 178255, upload-time = "2026-01-10T09:23:09.245Z" }, + { url = "https://files.pythonhosted.org/packages/6b/ae/90366304d7c2ce80f9b826096a9e9048b4bb760e44d3b873bb272cba696b/websockets-16.0-cp313-cp313-win_amd64.whl", hash = "sha256:3425ac5cf448801335d6fdc7ae1eb22072055417a96cc6b31b3861f455fbc156", size = 178689, upload-time = "2026-01-10T09:23:10.483Z" }, { url = "https://files.pythonhosted.org/packages/f3/1d/e88022630271f5bd349ed82417136281931e558d628dd52c4d8621b4a0b2/websockets-16.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8cc451a50f2aee53042ac52d2d053d08bf89bcb31ae799cb4487587661c038a0", size = 177406, upload-time = "2026-01-10T09:23:12.178Z" }, { url = "https://files.pythonhosted.org/packages/f2/78/e63be1bf0724eeb4616efb1ae1c9044f7c3953b7957799abb5915bffd38e/websockets-16.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:daa3b6ff70a9241cf6c7fc9e949d41232d9d7d26fd3522b1ad2b4d62487e9904", size = 175085, upload-time = "2026-01-10T09:23:13.511Z" }, { url = "https://files.pythonhosted.org/packages/bb/f4/d3c9220d818ee955ae390cf319a7c7a467beceb24f05ee7aaaa2414345ba/websockets-16.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:fd3cb4adb94a2a6e2b7c0d8d05cb94e6f1c81a0cf9dc2694fb65c7e8d94c42e4", size = 175328, upload-time = "2026-01-10T09:23:14.727Z" }, @@ -1954,6 +2584,54 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/57/63/0c6ebca57330cd313f6102b16dd57ffaf3ec4c83403dcb45dbd15c6f3ea1/yarl-1.22.0.tar.gz", hash = "sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71", size = 187169, upload-time = "2025-10-06T14:12:55.963Z" } wheels = [ + { url = "https://files.pythonhosted.org/packages/75/ff/46736024fee3429b80a165a732e38e5d5a238721e634ab41b040d49f8738/yarl-1.22.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e340382d1afa5d32b892b3ff062436d592ec3d692aeea3bef3a5cfe11bbf8c6f", size = 142000, upload-time = "2025-10-06T14:09:44.631Z" }, + { url = "https://files.pythonhosted.org/packages/5a/9a/b312ed670df903145598914770eb12de1bac44599549b3360acc96878df8/yarl-1.22.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f1e09112a2c31ffe8d80be1b0988fa6a18c5d5cad92a9ffbb1c04c91bfe52ad2", size = 94338, upload-time = "2025-10-06T14:09:46.372Z" }, + { url = "https://files.pythonhosted.org/packages/ba/f5/0601483296f09c3c65e303d60c070a5c19fcdbc72daa061e96170785bc7d/yarl-1.22.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:939fe60db294c786f6b7c2d2e121576628468f65453d86b0fe36cb52f987bd74", size = 94909, upload-time = "2025-10-06T14:09:48.648Z" }, + { url = "https://files.pythonhosted.org/packages/60/41/9a1fe0b73dbcefce72e46cf149b0e0a67612d60bfc90fb59c2b2efdfbd86/yarl-1.22.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e1651bf8e0398574646744c1885a41198eba53dc8a9312b954073f845c90a8df", size = 372940, upload-time = "2025-10-06T14:09:50.089Z" }, + { url = "https://files.pythonhosted.org/packages/17/7a/795cb6dfee561961c30b800f0ed616b923a2ec6258b5def2a00bf8231334/yarl-1.22.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b8a0588521a26bf92a57a1705b77b8b59044cdceccac7151bd8d229e66b8dedb", size = 345825, upload-time = "2025-10-06T14:09:52.142Z" }, + { url = "https://files.pythonhosted.org/packages/d7/93/a58f4d596d2be2ae7bab1a5846c4d270b894958845753b2c606d666744d3/yarl-1.22.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:42188e6a615c1a75bcaa6e150c3fe8f3e8680471a6b10150c5f7e83f47cc34d2", size = 386705, upload-time = "2025-10-06T14:09:54.128Z" }, + { url = "https://files.pythonhosted.org/packages/61/92/682279d0e099d0e14d7fd2e176bd04f48de1484f56546a3e1313cd6c8e7c/yarl-1.22.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f6d2cb59377d99718913ad9a151030d6f83ef420a2b8f521d94609ecc106ee82", size = 396518, upload-time = "2025-10-06T14:09:55.762Z" }, + { url = "https://files.pythonhosted.org/packages/db/0f/0d52c98b8a885aeda831224b78f3be7ec2e1aa4a62091f9f9188c3c65b56/yarl-1.22.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50678a3b71c751d58d7908edc96d332af328839eea883bb554a43f539101277a", size = 377267, upload-time = "2025-10-06T14:09:57.958Z" }, + { url = "https://files.pythonhosted.org/packages/22/42/d2685e35908cbeaa6532c1fc73e89e7f2efb5d8a7df3959ea8e37177c5a3/yarl-1.22.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e8fbaa7cec507aa24ea27a01456e8dd4b6fab829059b69844bd348f2d467124", size = 365797, upload-time = "2025-10-06T14:09:59.527Z" }, + { url = "https://files.pythonhosted.org/packages/a2/83/cf8c7bcc6355631762f7d8bdab920ad09b82efa6b722999dfb05afa6cfac/yarl-1.22.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:433885ab5431bc3d3d4f2f9bd15bfa1614c522b0f1405d62c4f926ccd69d04fa", size = 365535, upload-time = "2025-10-06T14:10:01.139Z" }, + { url = "https://files.pythonhosted.org/packages/25/e1/5302ff9b28f0c59cac913b91fe3f16c59a033887e57ce9ca5d41a3a94737/yarl-1.22.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:b790b39c7e9a4192dc2e201a282109ed2985a1ddbd5ac08dc56d0e121400a8f7", size = 382324, upload-time = "2025-10-06T14:10:02.756Z" }, + { url = "https://files.pythonhosted.org/packages/bf/cd/4617eb60f032f19ae3a688dc990d8f0d89ee0ea378b61cac81ede3e52fae/yarl-1.22.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31f0b53913220599446872d757257be5898019c85e7971599065bc55065dc99d", size = 383803, upload-time = "2025-10-06T14:10:04.552Z" }, + { url = "https://files.pythonhosted.org/packages/59/65/afc6e62bb506a319ea67b694551dab4a7e6fb7bf604e9bd9f3e11d575fec/yarl-1.22.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a49370e8f711daec68d09b821a34e1167792ee2d24d405cbc2387be4f158b520", size = 374220, upload-time = "2025-10-06T14:10:06.489Z" }, + { url = "https://files.pythonhosted.org/packages/e7/3d/68bf18d50dc674b942daec86a9ba922d3113d8399b0e52b9897530442da2/yarl-1.22.0-cp312-cp312-win32.whl", hash = "sha256:70dfd4f241c04bd9239d53b17f11e6ab672b9f1420364af63e8531198e3f5fe8", size = 81589, upload-time = "2025-10-06T14:10:09.254Z" }, + { url = "https://files.pythonhosted.org/packages/c8/9a/6ad1a9b37c2f72874f93e691b2e7ecb6137fb2b899983125db4204e47575/yarl-1.22.0-cp312-cp312-win_amd64.whl", hash = "sha256:8884d8b332a5e9b88e23f60bb166890009429391864c685e17bd73a9eda9105c", size = 87213, upload-time = "2025-10-06T14:10:11.369Z" }, + { url = "https://files.pythonhosted.org/packages/44/c5/c21b562d1680a77634d748e30c653c3ca918beb35555cff24986fff54598/yarl-1.22.0-cp312-cp312-win_arm64.whl", hash = "sha256:ea70f61a47f3cc93bdf8b2f368ed359ef02a01ca6393916bc8ff877427181e74", size = 81330, upload-time = "2025-10-06T14:10:13.112Z" }, + { url = "https://files.pythonhosted.org/packages/ea/f3/d67de7260456ee105dc1d162d43a019ecad6b91e2f51809d6cddaa56690e/yarl-1.22.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8dee9c25c74997f6a750cd317b8ca63545169c098faee42c84aa5e506c819b53", size = 139980, upload-time = "2025-10-06T14:10:14.601Z" }, + { url = "https://files.pythonhosted.org/packages/01/88/04d98af0b47e0ef42597b9b28863b9060bb515524da0a65d5f4db160b2d5/yarl-1.22.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:01e73b85a5434f89fc4fe27dcda2aff08ddf35e4d47bbbea3bdcd25321af538a", size = 93424, upload-time = "2025-10-06T14:10:16.115Z" }, + { url = "https://files.pythonhosted.org/packages/18/91/3274b215fd8442a03975ce6bee5fe6aa57a8326b29b9d3d56234a1dca244/yarl-1.22.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:22965c2af250d20c873cdbee8ff958fb809940aeb2e74ba5f20aaf6b7ac8c70c", size = 93821, upload-time = "2025-10-06T14:10:17.993Z" }, + { url = "https://files.pythonhosted.org/packages/61/3a/caf4e25036db0f2da4ca22a353dfeb3c9d3c95d2761ebe9b14df8fc16eb0/yarl-1.22.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b4f15793aa49793ec8d1c708ab7f9eded1aa72edc5174cae703651555ed1b601", size = 373243, upload-time = "2025-10-06T14:10:19.44Z" }, + { url = "https://files.pythonhosted.org/packages/6e/9e/51a77ac7516e8e7803b06e01f74e78649c24ee1021eca3d6a739cb6ea49c/yarl-1.22.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5542339dcf2747135c5c85f68680353d5cb9ffd741c0f2e8d832d054d41f35a", size = 342361, upload-time = "2025-10-06T14:10:21.124Z" }, + { url = "https://files.pythonhosted.org/packages/d4/f8/33b92454789dde8407f156c00303e9a891f1f51a0330b0fad7c909f87692/yarl-1.22.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5c401e05ad47a75869c3ab3e35137f8468b846770587e70d71e11de797d113df", size = 387036, upload-time = "2025-10-06T14:10:22.902Z" }, + { url = "https://files.pythonhosted.org/packages/d9/9a/c5db84ea024f76838220280f732970aa4ee154015d7f5c1bfb60a267af6f/yarl-1.22.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:243dda95d901c733f5b59214d28b0120893d91777cb8aa043e6ef059d3cddfe2", size = 397671, upload-time = "2025-10-06T14:10:24.523Z" }, + { url = "https://files.pythonhosted.org/packages/11/c9/cd8538dc2e7727095e0c1d867bad1e40c98f37763e6d995c1939f5fdc7b1/yarl-1.22.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bec03d0d388060058f5d291a813f21c011041938a441c593374da6077fe21b1b", size = 377059, upload-time = "2025-10-06T14:10:26.406Z" }, + { url = "https://files.pythonhosted.org/packages/a1/b9/ab437b261702ced75122ed78a876a6dec0a1b0f5e17a4ac7a9a2482d8abe/yarl-1.22.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0748275abb8c1e1e09301ee3cf90c8a99678a4e92e4373705f2a2570d581273", size = 365356, upload-time = "2025-10-06T14:10:28.461Z" }, + { url = "https://files.pythonhosted.org/packages/b2/9d/8e1ae6d1d008a9567877b08f0ce4077a29974c04c062dabdb923ed98e6fe/yarl-1.22.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:47fdb18187e2a4e18fda2c25c05d8251a9e4a521edaed757fef033e7d8498d9a", size = 361331, upload-time = "2025-10-06T14:10:30.541Z" }, + { url = "https://files.pythonhosted.org/packages/ca/5a/09b7be3905962f145b73beb468cdd53db8aa171cf18c80400a54c5b82846/yarl-1.22.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c7044802eec4524fde550afc28edda0dd5784c4c45f0be151a2d3ba017daca7d", size = 382590, upload-time = "2025-10-06T14:10:33.352Z" }, + { url = "https://files.pythonhosted.org/packages/aa/7f/59ec509abf90eda5048b0bc3e2d7b5099dffdb3e6b127019895ab9d5ef44/yarl-1.22.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:139718f35149ff544caba20fce6e8a2f71f1e39b92c700d8438a0b1d2a631a02", size = 385316, upload-time = "2025-10-06T14:10:35.034Z" }, + { url = "https://files.pythonhosted.org/packages/e5/84/891158426bc8036bfdfd862fabd0e0fa25df4176ec793e447f4b85cf1be4/yarl-1.22.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e1b51bebd221006d3d2f95fbe124b22b247136647ae5dcc8c7acafba66e5ee67", size = 374431, upload-time = "2025-10-06T14:10:37.76Z" }, + { url = "https://files.pythonhosted.org/packages/bb/49/03da1580665baa8bef5e8ed34c6df2c2aca0a2f28bf397ed238cc1bbc6f2/yarl-1.22.0-cp313-cp313-win32.whl", hash = "sha256:d3e32536234a95f513bd374e93d717cf6b2231a791758de6c509e3653f234c95", size = 81555, upload-time = "2025-10-06T14:10:39.649Z" }, + { url = "https://files.pythonhosted.org/packages/9a/ee/450914ae11b419eadd067c6183ae08381cfdfcb9798b90b2b713bbebddda/yarl-1.22.0-cp313-cp313-win_amd64.whl", hash = "sha256:47743b82b76d89a1d20b83e60d5c20314cbd5ba2befc9cda8f28300c4a08ed4d", size = 86965, upload-time = "2025-10-06T14:10:41.313Z" }, + { url = "https://files.pythonhosted.org/packages/98/4d/264a01eae03b6cf629ad69bae94e3b0e5344741e929073678e84bf7a3e3b/yarl-1.22.0-cp313-cp313-win_arm64.whl", hash = "sha256:5d0fcda9608875f7d052eff120c7a5da474a6796fe4d83e152e0e4d42f6d1a9b", size = 81205, upload-time = "2025-10-06T14:10:43.167Z" }, + { url = "https://files.pythonhosted.org/packages/88/fc/6908f062a2f77b5f9f6d69cecb1747260831ff206adcbc5b510aff88df91/yarl-1.22.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:719ae08b6972befcba4310e49edb1161a88cdd331e3a694b84466bd938a6ab10", size = 146209, upload-time = "2025-10-06T14:10:44.643Z" }, + { url = "https://files.pythonhosted.org/packages/65/47/76594ae8eab26210b4867be6f49129861ad33da1f1ebdf7051e98492bf62/yarl-1.22.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:47d8a5c446df1c4db9d21b49619ffdba90e77c89ec6e283f453856c74b50b9e3", size = 95966, upload-time = "2025-10-06T14:10:46.554Z" }, + { url = "https://files.pythonhosted.org/packages/ab/ce/05e9828a49271ba6b5b038b15b3934e996980dd78abdfeb52a04cfb9467e/yarl-1.22.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:cfebc0ac8333520d2d0423cbbe43ae43c8838862ddb898f5ca68565e395516e9", size = 97312, upload-time = "2025-10-06T14:10:48.007Z" }, + { url = "https://files.pythonhosted.org/packages/d1/c5/7dffad5e4f2265b29c9d7ec869c369e4223166e4f9206fc2243ee9eea727/yarl-1.22.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4398557cbf484207df000309235979c79c4356518fd5c99158c7d38203c4da4f", size = 361967, upload-time = "2025-10-06T14:10:49.997Z" }, + { url = "https://files.pythonhosted.org/packages/50/b2/375b933c93a54bff7fc041e1a6ad2c0f6f733ffb0c6e642ce56ee3b39970/yarl-1.22.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2ca6fd72a8cd803be290d42f2dec5cdcd5299eeb93c2d929bf060ad9efaf5de0", size = 323949, upload-time = "2025-10-06T14:10:52.004Z" }, + { url = "https://files.pythonhosted.org/packages/66/50/bfc2a29a1d78644c5a7220ce2f304f38248dc94124a326794e677634b6cf/yarl-1.22.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ca1f59c4e1ab6e72f0a23c13fca5430f889634166be85dbf1013683e49e3278e", size = 361818, upload-time = "2025-10-06T14:10:54.078Z" }, + { url = "https://files.pythonhosted.org/packages/46/96/f3941a46af7d5d0f0498f86d71275696800ddcdd20426298e572b19b91ff/yarl-1.22.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6c5010a52015e7c70f86eb967db0f37f3c8bd503a695a49f8d45700144667708", size = 372626, upload-time = "2025-10-06T14:10:55.767Z" }, + { url = "https://files.pythonhosted.org/packages/c1/42/8b27c83bb875cd89448e42cd627e0fb971fa1675c9ec546393d18826cb50/yarl-1.22.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d7672ecf7557476642c88497c2f8d8542f8e36596e928e9bcba0e42e1e7d71f", size = 341129, upload-time = "2025-10-06T14:10:57.985Z" }, + { url = "https://files.pythonhosted.org/packages/49/36/99ca3122201b382a3cf7cc937b95235b0ac944f7e9f2d5331d50821ed352/yarl-1.22.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:3b7c88eeef021579d600e50363e0b6ee4f7f6f728cd3486b9d0f3ee7b946398d", size = 346776, upload-time = "2025-10-06T14:10:59.633Z" }, + { url = "https://files.pythonhosted.org/packages/85/b4/47328bf996acd01a4c16ef9dcd2f59c969f495073616586f78cd5f2efb99/yarl-1.22.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f4afb5c34f2c6fecdcc182dfcfc6af6cccf1aa923eed4d6a12e9d96904e1a0d8", size = 334879, upload-time = "2025-10-06T14:11:01.454Z" }, + { url = "https://files.pythonhosted.org/packages/c2/ad/b77d7b3f14a4283bffb8e92c6026496f6de49751c2f97d4352242bba3990/yarl-1.22.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:59c189e3e99a59cf8d83cbb31d4db02d66cda5a1a4374e8a012b51255341abf5", size = 350996, upload-time = "2025-10-06T14:11:03.452Z" }, + { url = "https://files.pythonhosted.org/packages/81/c8/06e1d69295792ba54d556f06686cbd6a7ce39c22307100e3fb4a2c0b0a1d/yarl-1.22.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:5a3bf7f62a289fa90f1990422dc8dff5a458469ea71d1624585ec3a4c8d6960f", size = 356047, upload-time = "2025-10-06T14:11:05.115Z" }, + { url = "https://files.pythonhosted.org/packages/4b/b8/4c0e9e9f597074b208d18cef227d83aac36184bfbc6eab204ea55783dbc5/yarl-1.22.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:de6b9a04c606978fdfe72666fa216ffcf2d1a9f6a381058d4378f8d7b1e5de62", size = 342947, upload-time = "2025-10-06T14:11:08.137Z" }, + { url = "https://files.pythonhosted.org/packages/e0/e5/11f140a58bf4c6ad7aca69a892bff0ee638c31bea4206748fc0df4ebcb3a/yarl-1.22.0-cp313-cp313t-win32.whl", hash = "sha256:1834bb90991cc2999f10f97f5f01317f99b143284766d197e43cd5b45eb18d03", size = 86943, upload-time = "2025-10-06T14:11:10.284Z" }, + { url = "https://files.pythonhosted.org/packages/31/74/8b74bae38ed7fe6793d0c15a0c8207bbb819cf287788459e5ed230996cdd/yarl-1.22.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ff86011bd159a9d2dfc89c34cfd8aff12875980e3bd6a39ff097887520e60249", size = 93715, upload-time = "2025-10-06T14:11:11.739Z" }, + { url = "https://files.pythonhosted.org/packages/69/66/991858aa4b5892d57aef7ee1ba6b4d01ec3b7eb3060795d34090a3ca3278/yarl-1.22.0-cp313-cp313t-win_arm64.whl", hash = "sha256:7861058d0582b847bc4e3a4a4c46828a410bca738673f35a29ba3ca5db0b473b", size = 83857, upload-time = "2025-10-06T14:11:13.586Z" }, { url = "https://files.pythonhosted.org/packages/46/b3/e20ef504049f1a1c54a814b4b9bed96d1ac0e0610c3b4da178f87209db05/yarl-1.22.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:34b36c2c57124530884d89d50ed2c1478697ad7473efd59cfd479945c95650e4", size = 140520, upload-time = "2025-10-06T14:11:15.465Z" }, { url = "https://files.pythonhosted.org/packages/e4/04/3532d990fdbab02e5ede063676b5c4260e7f3abea2151099c2aa745acc4c/yarl-1.22.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:0dd9a702591ca2e543631c2a017e4a547e38a5c0f29eece37d9097e04a7ac683", size = 93504, upload-time = "2025-10-06T14:11:17.106Z" }, { url = "https://files.pythonhosted.org/packages/11/63/ff458113c5c2dac9a9719ac68ee7c947cb621432bcf28c9972b1c0e83938/yarl-1.22.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:594fcab1032e2d2cc3321bb2e51271e7cd2b516c7d9aee780ece81b07ff8244b", size = 94282, upload-time = "2025-10-06T14:11:19.064Z" }, From 9e9e0f3186d8c0551360f3b6d4a3e681a65ba68d Mon Sep 17 00:00:00 2001 From: Darief Maes Date: Thu, 23 Apr 2026 16:44:00 -0400 Subject: [PATCH 2/3] fix to issue with LLM --- .../fmsr_chiller_failure_modes_run_-1.json | 21 - .../fmsr_chiller_failure_modes_run_-2.json | 21 - .../fmsr_chiller_failure_modes_run_01.json | 21 - .../fmsr_chiller_failure_modes_run_02.json | 21 - .../fmsr_chiller_failure_modes_run_03.json | 21 - .../fmsr_chiller_failure_modes_run_04.json | 21 - .../fmsr_chiller_failure_modes_run_05.json | 21 - .../timing/runs/iot_assets_main_run_-1.json | 21 - .../timing/runs/iot_assets_main_run_-2.json | 21 - .../timing/runs/iot_assets_main_run_01.json | 23 -- .../timing/runs/iot_assets_main_run_02.json | 23 -- .../timing/runs/iot_assets_main_run_03.json | 23 -- .../timing/runs/iot_assets_main_run_04.json | 21 - .../timing/runs/iot_assets_main_run_05.json | 21 - .../runs/iot_assets_main_warmup_01.json | 23 -- .../runs/iot_observations_ch1_run_-1.json | 21 - .../runs/iot_observations_ch1_run_-2.json | 21 - .../runs/iot_observations_ch1_run_01.json | 21 - .../runs/iot_observations_ch1_run_02.json | 21 - .../runs/iot_observations_ch1_run_03.json | 21 - .../runs/iot_observations_ch1_run_04.json | 21 - .../runs/iot_observations_ch1_run_05.json | 21 - .../runs/iot_sensors_chiller_1_run_-1.json | 21 - .../runs/iot_sensors_chiller_1_run_-2.json | 21 - .../runs/iot_sensors_chiller_1_run_01.json | 21 - .../runs/iot_sensors_chiller_1_run_02.json | 21 - .../runs/iot_sensors_chiller_1_run_03.json | 21 - .../runs/iot_sensors_chiller_1_run_04.json | 21 - .../runs/iot_sensors_chiller_1_run_05.json | 21 - .../runs/iot_sensors_chiller_1_warmup_01.json | 23 -- .../timing/runs/utilities_time_run_-1.json | 21 - .../timing/runs/utilities_time_run_-2.json | 21 - .../timing/runs/utilities_time_run_01.json | 21 - .../timing/runs/utilities_time_run_02.json | 21 - .../timing/runs/utilities_time_run_03.json | 21 - .../timing/runs/utilities_time_run_04.json | 21 - .../timing/runs/utilities_time_run_05.json | 21 - src/evaluation/__init__.py | 0 src/evaluation/timing_benchmark.py | 380 ------------------ src/servers/iot/main.py | 13 +- src/workflow/executor.py | 112 +++++- src/workflow/planner.py | 2 + src/workflow/tests/test_runner.py | 2 +- 43 files changed, 117 insertions(+), 1179 deletions(-) delete mode 100644 artifacts/timing/runs/fmsr_chiller_failure_modes_run_-1.json delete mode 100644 artifacts/timing/runs/fmsr_chiller_failure_modes_run_-2.json delete mode 100644 artifacts/timing/runs/fmsr_chiller_failure_modes_run_01.json delete mode 100644 artifacts/timing/runs/fmsr_chiller_failure_modes_run_02.json delete mode 100644 artifacts/timing/runs/fmsr_chiller_failure_modes_run_03.json delete mode 100644 artifacts/timing/runs/fmsr_chiller_failure_modes_run_04.json delete mode 100644 artifacts/timing/runs/fmsr_chiller_failure_modes_run_05.json delete mode 100644 artifacts/timing/runs/iot_assets_main_run_-1.json delete mode 100644 artifacts/timing/runs/iot_assets_main_run_-2.json delete mode 100644 artifacts/timing/runs/iot_assets_main_run_01.json delete mode 100644 artifacts/timing/runs/iot_assets_main_run_02.json delete mode 100644 artifacts/timing/runs/iot_assets_main_run_03.json delete mode 100644 artifacts/timing/runs/iot_assets_main_run_04.json delete mode 100644 artifacts/timing/runs/iot_assets_main_run_05.json delete mode 100644 artifacts/timing/runs/iot_assets_main_warmup_01.json delete mode 100644 artifacts/timing/runs/iot_observations_ch1_run_-1.json delete mode 100644 artifacts/timing/runs/iot_observations_ch1_run_-2.json delete mode 100644 artifacts/timing/runs/iot_observations_ch1_run_01.json delete mode 100644 artifacts/timing/runs/iot_observations_ch1_run_02.json delete mode 100644 artifacts/timing/runs/iot_observations_ch1_run_03.json delete mode 100644 artifacts/timing/runs/iot_observations_ch1_run_04.json delete mode 100644 artifacts/timing/runs/iot_observations_ch1_run_05.json delete mode 100644 artifacts/timing/runs/iot_sensors_chiller_1_run_-1.json delete mode 100644 artifacts/timing/runs/iot_sensors_chiller_1_run_-2.json delete mode 100644 artifacts/timing/runs/iot_sensors_chiller_1_run_01.json delete mode 100644 artifacts/timing/runs/iot_sensors_chiller_1_run_02.json delete mode 100644 artifacts/timing/runs/iot_sensors_chiller_1_run_03.json delete mode 100644 artifacts/timing/runs/iot_sensors_chiller_1_run_04.json delete mode 100644 artifacts/timing/runs/iot_sensors_chiller_1_run_05.json delete mode 100644 artifacts/timing/runs/iot_sensors_chiller_1_warmup_01.json delete mode 100644 artifacts/timing/runs/utilities_time_run_-1.json delete mode 100644 artifacts/timing/runs/utilities_time_run_-2.json delete mode 100644 artifacts/timing/runs/utilities_time_run_01.json delete mode 100644 artifacts/timing/runs/utilities_time_run_02.json delete mode 100644 artifacts/timing/runs/utilities_time_run_03.json delete mode 100644 artifacts/timing/runs/utilities_time_run_04.json delete mode 100644 artifacts/timing/runs/utilities_time_run_05.json delete mode 100644 src/evaluation/__init__.py delete mode 100644 src/evaluation/timing_benchmark.py diff --git a/artifacts/timing/runs/fmsr_chiller_failure_modes_run_-1.json b/artifacts/timing/runs/fmsr_chiller_failure_modes_run_-1.json deleted file mode 100644 index 6a638a743..000000000 --- a/artifacts/timing/runs/fmsr_chiller_failure_modes_run_-1.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "fmsr_chiller_failure_modes_run_-1", - "group": "fmsr_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 10.858443, - "average_seconds": 10.858443 - } - }, - "total_wall_time_seconds": 10.858827, - "metadata": { - "scenario_name": "fmsr_chiller_failure_modes", - "question_length_chars": 39, - "plan_steps": 2, - "tool_calls": 1, - "server_sequence": "IoTAgent,FMSRAgent", - "unique_servers": "FMSRAgent,IoTAgent" - }, - "created_at_unix": 1775495981.597656 -} \ No newline at end of file diff --git a/artifacts/timing/runs/fmsr_chiller_failure_modes_run_-2.json b/artifacts/timing/runs/fmsr_chiller_failure_modes_run_-2.json deleted file mode 100644 index 015cb1a7d..000000000 --- a/artifacts/timing/runs/fmsr_chiller_failure_modes_run_-2.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "fmsr_chiller_failure_modes_run_-2", - "group": "fmsr_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 17.802149, - "average_seconds": 17.802149 - } - }, - "total_wall_time_seconds": 17.802449, - "metadata": { - "scenario_name": "fmsr_chiller_failure_modes", - "question_length_chars": 39, - "plan_steps": 3, - "tool_calls": 2, - "server_sequence": "FMSRAgent,IoTAgent,FMSRAgent", - "unique_servers": "FMSRAgent,IoTAgent" - }, - "created_at_unix": 1775495999.400982 -} \ No newline at end of file diff --git a/artifacts/timing/runs/fmsr_chiller_failure_modes_run_01.json b/artifacts/timing/runs/fmsr_chiller_failure_modes_run_01.json deleted file mode 100644 index 5ab289aa4..000000000 --- a/artifacts/timing/runs/fmsr_chiller_failure_modes_run_01.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "fmsr_chiller_failure_modes_run_01", - "group": "fmsr_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 13.492398, - "average_seconds": 13.492398 - } - }, - "total_wall_time_seconds": 13.49285, - "metadata": { - "scenario_name": "fmsr_chiller_failure_modes", - "question_length_chars": 39, - "plan_steps": 2, - "tool_calls": 2, - "server_sequence": "FMSRAgent,FMSRAgent", - "unique_servers": "FMSRAgent" - }, - "created_at_unix": 1775496012.895334 -} \ No newline at end of file diff --git a/artifacts/timing/runs/fmsr_chiller_failure_modes_run_02.json b/artifacts/timing/runs/fmsr_chiller_failure_modes_run_02.json deleted file mode 100644 index cd9787c17..000000000 --- a/artifacts/timing/runs/fmsr_chiller_failure_modes_run_02.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "fmsr_chiller_failure_modes_run_02", - "group": "fmsr_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 14.738207, - "average_seconds": 14.738207 - } - }, - "total_wall_time_seconds": 14.738572, - "metadata": { - "scenario_name": "fmsr_chiller_failure_modes", - "question_length_chars": 39, - "plan_steps": 3, - "tool_calls": 2, - "server_sequence": "IoTAgent,IoTAgent,FMSRAgent", - "unique_servers": "FMSRAgent,IoTAgent" - }, - "created_at_unix": 1775496027.6353002 -} \ No newline at end of file diff --git a/artifacts/timing/runs/fmsr_chiller_failure_modes_run_03.json b/artifacts/timing/runs/fmsr_chiller_failure_modes_run_03.json deleted file mode 100644 index f34c7acfb..000000000 --- a/artifacts/timing/runs/fmsr_chiller_failure_modes_run_03.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "fmsr_chiller_failure_modes_run_03", - "group": "fmsr_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 16.520928, - "average_seconds": 16.520928 - } - }, - "total_wall_time_seconds": 16.521396, - "metadata": { - "scenario_name": "fmsr_chiller_failure_modes", - "question_length_chars": 39, - "plan_steps": 3, - "tool_calls": 2, - "server_sequence": "IoTAgent,IoTAgent,FMSRAgent", - "unique_servers": "FMSRAgent,IoTAgent" - }, - "created_at_unix": 1775496044.157592 -} \ No newline at end of file diff --git a/artifacts/timing/runs/fmsr_chiller_failure_modes_run_04.json b/artifacts/timing/runs/fmsr_chiller_failure_modes_run_04.json deleted file mode 100644 index 52b4e4544..000000000 --- a/artifacts/timing/runs/fmsr_chiller_failure_modes_run_04.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "fmsr_chiller_failure_modes_run_04", - "group": "fmsr_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 16.560545, - "average_seconds": 16.560545 - } - }, - "total_wall_time_seconds": 16.561162, - "metadata": { - "scenario_name": "fmsr_chiller_failure_modes", - "question_length_chars": 39, - "plan_steps": 3, - "tool_calls": 2, - "server_sequence": "FMSRAgent,IoTAgent,FMSRAgent", - "unique_servers": "FMSRAgent,IoTAgent" - }, - "created_at_unix": 1775496060.7210398 -} \ No newline at end of file diff --git a/artifacts/timing/runs/fmsr_chiller_failure_modes_run_05.json b/artifacts/timing/runs/fmsr_chiller_failure_modes_run_05.json deleted file mode 100644 index 28efe57e6..000000000 --- a/artifacts/timing/runs/fmsr_chiller_failure_modes_run_05.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "fmsr_chiller_failure_modes_run_05", - "group": "fmsr_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 17.429605, - "average_seconds": 17.429605 - } - }, - "total_wall_time_seconds": 17.430239, - "metadata": { - "scenario_name": "fmsr_chiller_failure_modes", - "question_length_chars": 39, - "plan_steps": 3, - "tool_calls": 2, - "server_sequence": "FMSRAgent,IoTAgent,FMSRAgent", - "unique_servers": "FMSRAgent,IoTAgent" - }, - "created_at_unix": 1775496078.1532428 -} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_assets_main_run_-1.json b/artifacts/timing/runs/iot_assets_main_run_-1.json deleted file mode 100644 index caee9be8f..000000000 --- a/artifacts/timing/runs/iot_assets_main_run_-1.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "iot_assets_main_run_-1", - "group": "iot_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 8.33804, - "average_seconds": 8.33804 - } - }, - "total_wall_time_seconds": 8.338263, - "metadata": { - "scenario_name": "iot_assets_main", - "question_length_chars": 33, - "plan_steps": 1, - "tool_calls": 1, - "server_sequence": "IoTAgent", - "unique_servers": "IoTAgent" - }, - "created_at_unix": 1775495862.19991 -} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_assets_main_run_-2.json b/artifacts/timing/runs/iot_assets_main_run_-2.json deleted file mode 100644 index 8aefe0836..000000000 --- a/artifacts/timing/runs/iot_assets_main_run_-2.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "iot_assets_main_run_-2", - "group": "iot_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 5.335888, - "average_seconds": 5.335888 - } - }, - "total_wall_time_seconds": 5.33635, - "metadata": { - "scenario_name": "iot_assets_main", - "question_length_chars": 33, - "plan_steps": 1, - "tool_calls": 1, - "server_sequence": "IoTAgent", - "unique_servers": "IoTAgent" - }, - "created_at_unix": 1775495867.5374138 -} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_assets_main_run_01.json b/artifacts/timing/runs/iot_assets_main_run_01.json deleted file mode 100644 index 5b1d69245..000000000 --- a/artifacts/timing/runs/iot_assets_main_run_01.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "run_name": "iot_assets_main_run_01", - "group": "iot_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 4.111411, - "average_seconds": 4.111411 - } - }, - "total_wall_time_seconds": 4.111804, - "metadata": { - "scenario_name": "iot_assets_main", - "success": true, - "failure_reason": "", - "question_length_chars": 33, - "plan_steps": 1, - "tool_calls": 1, - "server_sequence": "IoTAgent", - "unique_servers": "IoTAgent" - }, - "created_at_unix": 1775496687.418485 -} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_assets_main_run_02.json b/artifacts/timing/runs/iot_assets_main_run_02.json deleted file mode 100644 index d539c3200..000000000 --- a/artifacts/timing/runs/iot_assets_main_run_02.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "run_name": "iot_assets_main_run_02", - "group": "iot_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 4.587812, - "average_seconds": 4.587812 - } - }, - "total_wall_time_seconds": 4.588275, - "metadata": { - "scenario_name": "iot_assets_main", - "success": true, - "failure_reason": "", - "question_length_chars": 33, - "plan_steps": 1, - "tool_calls": 1, - "server_sequence": "IoTAgent", - "unique_servers": "IoTAgent" - }, - "created_at_unix": 1775496693.509748 -} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_assets_main_run_03.json b/artifacts/timing/runs/iot_assets_main_run_03.json deleted file mode 100644 index b230df81a..000000000 --- a/artifacts/timing/runs/iot_assets_main_run_03.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "run_name": "iot_assets_main_run_03", - "group": "iot_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 4.810847, - "average_seconds": 4.810847 - } - }, - "total_wall_time_seconds": 4.811266, - "metadata": { - "scenario_name": "iot_assets_main", - "success": true, - "failure_reason": "", - "question_length_chars": 33, - "plan_steps": 1, - "tool_calls": 1, - "server_sequence": "IoTAgent", - "unique_servers": "IoTAgent" - }, - "created_at_unix": 1775496699.823505 -} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_assets_main_run_04.json b/artifacts/timing/runs/iot_assets_main_run_04.json deleted file mode 100644 index 2569f81be..000000000 --- a/artifacts/timing/runs/iot_assets_main_run_04.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "iot_assets_main_run_04", - "group": "iot_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 4.839655, - "average_seconds": 4.839655 - } - }, - "total_wall_time_seconds": 4.840056, - "metadata": { - "scenario_name": "iot_assets_main", - "question_length_chars": 33, - "plan_steps": 1, - "tool_calls": 1, - "server_sequence": "IoTAgent", - "unique_servers": "IoTAgent" - }, - "created_at_unix": 1775495887.4010198 -} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_assets_main_run_05.json b/artifacts/timing/runs/iot_assets_main_run_05.json deleted file mode 100644 index 47d511210..000000000 --- a/artifacts/timing/runs/iot_assets_main_run_05.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "iot_assets_main_run_05", - "group": "iot_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 5.641701, - "average_seconds": 5.641701 - } - }, - "total_wall_time_seconds": 5.64202, - "metadata": { - "scenario_name": "iot_assets_main", - "question_length_chars": 33, - "plan_steps": 1, - "tool_calls": 1, - "server_sequence": "IoTAgent", - "unique_servers": "IoTAgent" - }, - "created_at_unix": 1775495893.044065 -} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_assets_main_warmup_01.json b/artifacts/timing/runs/iot_assets_main_warmup_01.json deleted file mode 100644 index af10a45ea..000000000 --- a/artifacts/timing/runs/iot_assets_main_warmup_01.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "run_name": "iot_assets_main_warmup_01", - "group": "iot_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 6.610018, - "average_seconds": 6.610018 - } - }, - "total_wall_time_seconds": 6.610272, - "metadata": { - "scenario_name": "iot_assets_main", - "success": true, - "failure_reason": "", - "question_length_chars": 33, - "plan_steps": 1, - "tool_calls": 1, - "server_sequence": "IoTAgent", - "unique_servers": "IoTAgent" - }, - "created_at_unix": 1775496681.803185 -} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_observations_ch1_run_-1.json b/artifacts/timing/runs/iot_observations_ch1_run_-1.json deleted file mode 100644 index a49581433..000000000 --- a/artifacts/timing/runs/iot_observations_ch1_run_-1.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "iot_observations_ch1_run_-1", - "group": "iot_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 39.287675, - "average_seconds": 39.287675 - } - }, - "total_wall_time_seconds": 39.28824, - "metadata": { - "scenario_name": "iot_observations_ch1", - "question_length_chars": 41, - "plan_steps": 6, - "tool_calls": 4, - "server_sequence": "IoTAgent,none,IoTAgent,Utilities,IoTAgent,none", - "unique_servers": "IoTAgent,Utilities,none" - }, - "created_at_unix": 1775496146.766182 -} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_observations_ch1_run_-2.json b/artifacts/timing/runs/iot_observations_ch1_run_-2.json deleted file mode 100644 index 7aebfc6bd..000000000 --- a/artifacts/timing/runs/iot_observations_ch1_run_-2.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "iot_observations_ch1_run_-2", - "group": "iot_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 32.346201, - "average_seconds": 32.346201 - } - }, - "total_wall_time_seconds": 32.34678, - "metadata": { - "scenario_name": "iot_observations_ch1", - "question_length_chars": 41, - "plan_steps": 6, - "tool_calls": 3, - "server_sequence": "Utilities,IoTAgent,none,none,IoTAgent,none", - "unique_servers": "IoTAgent,Utilities,none" - }, - "created_at_unix": 1775496179.116521 -} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_observations_ch1_run_01.json b/artifacts/timing/runs/iot_observations_ch1_run_01.json deleted file mode 100644 index 8201f4bdd..000000000 --- a/artifacts/timing/runs/iot_observations_ch1_run_01.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "iot_observations_ch1_run_01", - "group": "iot_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 23.450538, - "average_seconds": 23.450538 - } - }, - "total_wall_time_seconds": 23.451171, - "metadata": { - "scenario_name": "iot_observations_ch1", - "question_length_chars": 41, - "plan_steps": 6, - "tool_calls": 4, - "server_sequence": "IoTAgent,IoTAgent,IoTAgent,none,IoTAgent,none", - "unique_servers": "IoTAgent,none" - }, - "created_at_unix": 1775496202.569411 -} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_observations_ch1_run_02.json b/artifacts/timing/runs/iot_observations_ch1_run_02.json deleted file mode 100644 index 01f051a96..000000000 --- a/artifacts/timing/runs/iot_observations_ch1_run_02.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "iot_observations_ch1_run_02", - "group": "iot_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 21.399007, - "average_seconds": 21.399007 - } - }, - "total_wall_time_seconds": 21.39962, - "metadata": { - "scenario_name": "iot_observations_ch1", - "question_length_chars": 41, - "plan_steps": 6, - "tool_calls": 5, - "server_sequence": "IoTAgent,IoTAgent,none,IoTAgent,Utilities,IoTAgent", - "unique_servers": "IoTAgent,Utilities,none" - }, - "created_at_unix": 1775496223.9713979 -} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_observations_ch1_run_03.json b/artifacts/timing/runs/iot_observations_ch1_run_03.json deleted file mode 100644 index 7b760b85c..000000000 --- a/artifacts/timing/runs/iot_observations_ch1_run_03.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "iot_observations_ch1_run_03", - "group": "iot_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 31.433882, - "average_seconds": 31.433882 - } - }, - "total_wall_time_seconds": 31.434382, - "metadata": { - "scenario_name": "iot_observations_ch1", - "question_length_chars": 41, - "plan_steps": 5, - "tool_calls": 4, - "server_sequence": "IoTAgent,Utilities,IoTAgent,none,Utilities", - "unique_servers": "IoTAgent,Utilities,none" - }, - "created_at_unix": 1775496255.408129 -} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_observations_ch1_run_04.json b/artifacts/timing/runs/iot_observations_ch1_run_04.json deleted file mode 100644 index 563456d29..000000000 --- a/artifacts/timing/runs/iot_observations_ch1_run_04.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "iot_observations_ch1_run_04", - "group": "iot_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 28.356606, - "average_seconds": 28.356606 - } - }, - "total_wall_time_seconds": 28.357171, - "metadata": { - "scenario_name": "iot_observations_ch1", - "question_length_chars": 41, - "plan_steps": 6, - "tool_calls": 3, - "server_sequence": "IoTAgent,none,IoTAgent,none,IoTAgent,none", - "unique_servers": "IoTAgent,none" - }, - "created_at_unix": 1775496283.766704 -} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_observations_ch1_run_05.json b/artifacts/timing/runs/iot_observations_ch1_run_05.json deleted file mode 100644 index 28f1c8342..000000000 --- a/artifacts/timing/runs/iot_observations_ch1_run_05.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "iot_observations_ch1_run_05", - "group": "iot_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 29.91934, - "average_seconds": 29.91934 - } - }, - "total_wall_time_seconds": 29.919652, - "metadata": { - "scenario_name": "iot_observations_ch1", - "question_length_chars": 41, - "plan_steps": 6, - "tool_calls": 5, - "server_sequence": "IoTAgent,IoTAgent,none,IoTAgent,Utilities,IoTAgent", - "unique_servers": "IoTAgent,Utilities,none" - }, - "created_at_unix": 1775496313.687286 -} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_sensors_chiller_1_run_-1.json b/artifacts/timing/runs/iot_sensors_chiller_1_run_-1.json deleted file mode 100644 index 9808e734b..000000000 --- a/artifacts/timing/runs/iot_sensors_chiller_1_run_-1.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "iot_sensors_chiller_1_run_-1", - "group": "iot_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 12.511002, - "average_seconds": 12.511002 - } - }, - "total_wall_time_seconds": 12.511309, - "metadata": { - "scenario_name": "iot_sensors_chiller_1", - "question_length_chars": 44, - "plan_steps": 3, - "tool_calls": 2, - "server_sequence": "IoTAgent,none,IoTAgent", - "unique_servers": "IoTAgent,none" - }, - "created_at_unix": 1775495905.555922 -} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_sensors_chiller_1_run_-2.json b/artifacts/timing/runs/iot_sensors_chiller_1_run_-2.json deleted file mode 100644 index 782d166b1..000000000 --- a/artifacts/timing/runs/iot_sensors_chiller_1_run_-2.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "iot_sensors_chiller_1_run_-2", - "group": "iot_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 8.951102, - "average_seconds": 8.951102 - } - }, - "total_wall_time_seconds": 8.951563, - "metadata": { - "scenario_name": "iot_sensors_chiller_1", - "question_length_chars": 44, - "plan_steps": 3, - "tool_calls": 2, - "server_sequence": "IoTAgent,none,IoTAgent", - "unique_servers": "IoTAgent,none" - }, - "created_at_unix": 1775495914.5095239 -} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_sensors_chiller_1_run_01.json b/artifacts/timing/runs/iot_sensors_chiller_1_run_01.json deleted file mode 100644 index 06d6e7ef6..000000000 --- a/artifacts/timing/runs/iot_sensors_chiller_1_run_01.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "iot_sensors_chiller_1_run_01", - "group": "iot_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 10.607203, - "average_seconds": 10.607203 - } - }, - "total_wall_time_seconds": 10.60754, - "metadata": { - "scenario_name": "iot_sensors_chiller_1", - "question_length_chars": 44, - "plan_steps": 3, - "tool_calls": 2, - "server_sequence": "IoTAgent,none,IoTAgent", - "unique_servers": "IoTAgent,none" - }, - "created_at_unix": 1775495925.117853 -} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_sensors_chiller_1_run_02.json b/artifacts/timing/runs/iot_sensors_chiller_1_run_02.json deleted file mode 100644 index 2de307ca2..000000000 --- a/artifacts/timing/runs/iot_sensors_chiller_1_run_02.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "iot_sensors_chiller_1_run_02", - "group": "iot_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 12.569179, - "average_seconds": 12.569179 - } - }, - "total_wall_time_seconds": 12.569651, - "metadata": { - "scenario_name": "iot_sensors_chiller_1", - "question_length_chars": 44, - "plan_steps": 3, - "tool_calls": 2, - "server_sequence": "IoTAgent,none,IoTAgent", - "unique_servers": "IoTAgent,none" - }, - "created_at_unix": 1775495937.689574 -} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_sensors_chiller_1_run_03.json b/artifacts/timing/runs/iot_sensors_chiller_1_run_03.json deleted file mode 100644 index 80aae9e5a..000000000 --- a/artifacts/timing/runs/iot_sensors_chiller_1_run_03.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "iot_sensors_chiller_1_run_03", - "group": "iot_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 8.479029, - "average_seconds": 8.479029 - } - }, - "total_wall_time_seconds": 8.479517, - "metadata": { - "scenario_name": "iot_sensors_chiller_1", - "question_length_chars": 44, - "plan_steps": 3, - "tool_calls": 2, - "server_sequence": "IoTAgent,none,IoTAgent", - "unique_servers": "IoTAgent,none" - }, - "created_at_unix": 1775495946.169792 -} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_sensors_chiller_1_run_04.json b/artifacts/timing/runs/iot_sensors_chiller_1_run_04.json deleted file mode 100644 index 208b58f70..000000000 --- a/artifacts/timing/runs/iot_sensors_chiller_1_run_04.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "iot_sensors_chiller_1_run_04", - "group": "iot_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 10.976555, - "average_seconds": 10.976555 - } - }, - "total_wall_time_seconds": 10.977128, - "metadata": { - "scenario_name": "iot_sensors_chiller_1", - "question_length_chars": 44, - "plan_steps": 3, - "tool_calls": 2, - "server_sequence": "IoTAgent,none,IoTAgent", - "unique_servers": "IoTAgent,none" - }, - "created_at_unix": 1775495957.149072 -} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_sensors_chiller_1_run_05.json b/artifacts/timing/runs/iot_sensors_chiller_1_run_05.json deleted file mode 100644 index 0170a1808..000000000 --- a/artifacts/timing/runs/iot_sensors_chiller_1_run_05.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "iot_sensors_chiller_1_run_05", - "group": "iot_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 13.517921, - "average_seconds": 13.517921 - } - }, - "total_wall_time_seconds": 13.518375, - "metadata": { - "scenario_name": "iot_sensors_chiller_1", - "question_length_chars": 44, - "plan_steps": 3, - "tool_calls": 2, - "server_sequence": "IoTAgent,none,IoTAgent", - "unique_servers": "IoTAgent,none" - }, - "created_at_unix": 1775495970.7372491 -} \ No newline at end of file diff --git a/artifacts/timing/runs/iot_sensors_chiller_1_warmup_01.json b/artifacts/timing/runs/iot_sensors_chiller_1_warmup_01.json deleted file mode 100644 index f73840f43..000000000 --- a/artifacts/timing/runs/iot_sensors_chiller_1_warmup_01.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "run_name": "iot_sensors_chiller_1_warmup_01", - "group": "iot_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 7.502668, - "average_seconds": 7.502668 - } - }, - "total_wall_time_seconds": 7.503349, - "metadata": { - "scenario_name": "iot_sensors_chiller_1", - "success": false, - "failure_reason": "planner_emitted_agent_none | Unknown agent 'none'. Registered agents: ['IoTAgent', 'Utilities', 'FMSRAgent', 'TSFMAgent']", - "question_length_chars": 44, - "plan_steps": 3, - "tool_calls": 2, - "server_sequence": "IoTAgent,none,IoTAgent", - "unique_servers": "IoTAgent,none" - }, - "created_at_unix": 1775496708.830985 -} \ No newline at end of file diff --git a/artifacts/timing/runs/utilities_time_run_-1.json b/artifacts/timing/runs/utilities_time_run_-1.json deleted file mode 100644 index 468c701c0..000000000 --- a/artifacts/timing/runs/utilities_time_run_-1.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "utilities_time_run_-1", - "group": "utilities_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 4.707929, - "average_seconds": 4.707929 - } - }, - "total_wall_time_seconds": 4.708558, - "metadata": { - "scenario_name": "utilities_time", - "question_length_chars": 25, - "plan_steps": 1, - "tool_calls": 1, - "server_sequence": "Utilities", - "unique_servers": "Utilities" - }, - "created_at_unix": 1775496082.864054 -} \ No newline at end of file diff --git a/artifacts/timing/runs/utilities_time_run_-2.json b/artifacts/timing/runs/utilities_time_run_-2.json deleted file mode 100644 index 6066b80e0..000000000 --- a/artifacts/timing/runs/utilities_time_run_-2.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "utilities_time_run_-2", - "group": "utilities_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 3.685504, - "average_seconds": 3.685504 - } - }, - "total_wall_time_seconds": 3.686068, - "metadata": { - "scenario_name": "utilities_time", - "question_length_chars": 25, - "plan_steps": 1, - "tool_calls": 1, - "server_sequence": "Utilities", - "unique_servers": "Utilities" - }, - "created_at_unix": 1775496086.552075 -} \ No newline at end of file diff --git a/artifacts/timing/runs/utilities_time_run_01.json b/artifacts/timing/runs/utilities_time_run_01.json deleted file mode 100644 index 83278b608..000000000 --- a/artifacts/timing/runs/utilities_time_run_01.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "utilities_time_run_01", - "group": "utilities_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 3.992103, - "average_seconds": 3.992103 - } - }, - "total_wall_time_seconds": 3.992689, - "metadata": { - "scenario_name": "utilities_time", - "question_length_chars": 25, - "plan_steps": 1, - "tool_calls": 1, - "server_sequence": "Utilities", - "unique_servers": "Utilities" - }, - "created_at_unix": 1775496090.547076 -} \ No newline at end of file diff --git a/artifacts/timing/runs/utilities_time_run_02.json b/artifacts/timing/runs/utilities_time_run_02.json deleted file mode 100644 index 133967d34..000000000 --- a/artifacts/timing/runs/utilities_time_run_02.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "utilities_time_run_02", - "group": "utilities_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 4.351466, - "average_seconds": 4.351466 - } - }, - "total_wall_time_seconds": 4.352046, - "metadata": { - "scenario_name": "utilities_time", - "question_length_chars": 25, - "plan_steps": 1, - "tool_calls": 1, - "server_sequence": "Utilities", - "unique_servers": "Utilities" - }, - "created_at_unix": 1775496094.9015522 -} \ No newline at end of file diff --git a/artifacts/timing/runs/utilities_time_run_03.json b/artifacts/timing/runs/utilities_time_run_03.json deleted file mode 100644 index 40090477f..000000000 --- a/artifacts/timing/runs/utilities_time_run_03.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "utilities_time_run_03", - "group": "utilities_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 3.934517, - "average_seconds": 3.934517 - } - }, - "total_wall_time_seconds": 3.935077, - "metadata": { - "scenario_name": "utilities_time", - "question_length_chars": 25, - "plan_steps": 1, - "tool_calls": 1, - "server_sequence": "Utilities", - "unique_servers": "Utilities" - }, - "created_at_unix": 1775496098.838848 -} \ No newline at end of file diff --git a/artifacts/timing/runs/utilities_time_run_04.json b/artifacts/timing/runs/utilities_time_run_04.json deleted file mode 100644 index 92e4583c9..000000000 --- a/artifacts/timing/runs/utilities_time_run_04.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "utilities_time_run_04", - "group": "utilities_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 4.815199, - "average_seconds": 4.815199 - } - }, - "total_wall_time_seconds": 4.815743, - "metadata": { - "scenario_name": "utilities_time", - "question_length_chars": 25, - "plan_steps": 1, - "tool_calls": 1, - "server_sequence": "Utilities", - "unique_servers": "Utilities" - }, - "created_at_unix": 1775496103.6566458 -} \ No newline at end of file diff --git a/artifacts/timing/runs/utilities_time_run_05.json b/artifacts/timing/runs/utilities_time_run_05.json deleted file mode 100644 index 55fce349a..000000000 --- a/artifacts/timing/runs/utilities_time_run_05.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "run_name": "utilities_time_run_05", - "group": "utilities_only", - "phases": { - "question_to_answer": { - "count": 1, - "total_seconds": 3.81609, - "average_seconds": 3.81609 - } - }, - "total_wall_time_seconds": 3.816603, - "metadata": { - "scenario_name": "utilities_time", - "question_length_chars": 25, - "plan_steps": 1, - "tool_calls": 1, - "server_sequence": "Utilities", - "unique_servers": "Utilities" - }, - "created_at_unix": 1775496107.4759 -} \ No newline at end of file diff --git a/src/evaluation/__init__.py b/src/evaluation/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/evaluation/timing_benchmark.py b/src/evaluation/timing_benchmark.py deleted file mode 100644 index 55e0228d2..000000000 --- a/src/evaluation/timing_benchmark.py +++ /dev/null @@ -1,380 +0,0 @@ -"""Timing benchmark runner for AssetOpsBench orchestration evaluation. - -This script runs repeated timing benchmarks over the single-agent meta-agent -scenario files, logs each run to Weights & Biases via ``workflow.timing``, -and writes aggregate JSON summaries grouped by workload class. -""" - -from __future__ import annotations - -import argparse -import asyncio -import json -import statistics -from collections import defaultdict -from dataclasses import dataclass -from pathlib import Path -from typing import Any - -from dotenv import load_dotenv - -from llm.litellm import LiteLLMBackend -from workflow.runner import PlanExecuteRunner -from workflow.timing import TimingRun - -_SCENARIO_ROOT = Path("src/tmp/meta_agent/scenarios/single_agent") -_IOT_SCENARIO_PATH = _SCENARIO_ROOT / "iot_utterance_meta.json" -_FMSR_SCENARIO_PATH = _SCENARIO_ROOT / "fmsr_utterance.json" - - -@dataclass(frozen=True) -class Scenario: - scenario_id: int - name: str - group: str - question: str - source_file: str - source_type: str - category: str | None = None - deterministic: bool | None = None - - -def _build_parser() -> argparse.ArgumentParser: - parser = argparse.ArgumentParser( - description="Run repeated timing benchmarks for AssetOpsBench scenarios." - ) - parser.add_argument( - "--model-id", - default="watsonx/meta-llama/llama-4-maverick-17b-128e-instruct-fp8", - help="LLM model id used by the orchestration runner.", - ) - parser.add_argument( - "--warmup-runs", - type=int, - default=2, - help="Number of warmup runs per scenario to discard.", - ) - parser.add_argument( - "--measured-runs", - type=int, - default=5, - help="Number of measured runs per scenario.", - ) - parser.add_argument( - "--output-dir", - default="artifacts/timing", - help="Directory for per-run and aggregate JSON output.", - ) - parser.add_argument( - "--wandb-project", - required=True, - help="Weights & Biases project name for logging timed runs.", - ) - parser.add_argument( - "--wandb-entity", - default=None, - help="Optional Weights & Biases entity.", - ) - parser.add_argument( - "--wandb-mode", - default=None, - help="Optional Weights & Biases mode, for example 'offline'.", - ) - parser.add_argument( - "--retry-delay-seconds", - type=float, - default=3.0, - help="Delay before retrying a failed or rate-limited scenario run.", - ) - parser.add_argument( - "--inter-run-delay-seconds", - type=float, - default=0.5, - help="Delay between successful runs to reduce provider rate limiting.", - ) - parser.add_argument( - "--max-attempts-multiplier", - type=int, - default=3, - help="Maximum attempts per requested run count multiplier before giving up.", - ) - return parser - - -def _load_scenarios() -> list[Scenario]: - scenarios: list[Scenario] = [] - scenario_specs = [ - (_IOT_SCENARIO_PATH, "iot"), - (_FMSR_SCENARIO_PATH, "fmsr"), - ] - - for path, group in scenario_specs: - records = json.loads(path.read_text()) - for record in records: - scenario_id = int(record["id"]) - scenarios.append( - Scenario( - scenario_id=scenario_id, - name=f"{group}_{scenario_id}", - group=group, - question=record["text"], - source_file=str(path), - source_type=str(record.get("type", group)), - category=record.get("category"), - deterministic=record.get("deterministic"), - ) - ) - - return scenarios - - -def _classify_failure(result, plan) -> list[str]: - failure_reasons: list[str] = [] - - for step in result.history: - if step.success: - continue - error_text = step.error or "unknown_step_error" - failure_reasons.append(error_text) - lowered = error_text.lower() - if ( - "rate limit" in lowered - or "status_code\":429" in lowered - or "status code 429" in lowered - or "rate_limit_reached_requests" in lowered - or "consumption_limit_reached" in lowered - ): - failure_reasons.append("rate_limited") - if "token_quota_reached" in lowered or "quota" in lowered: - failure_reasons.append("quota_exhausted") - - return list(dict.fromkeys(failure_reasons)) - - -async def _run_scenario_once( - *, - scenario: Scenario, - model_id: str, - output_dir: Path, - wandb_project: str, - wandb_entity: str | None, - wandb_mode: str | None, - run_index: int, -) -> tuple[dict[str, Any], bool, str | None]: - llm = LiteLLMBackend(model_id=model_id) - runner = PlanExecuteRunner(llm=llm) - - run_label = ( - f"warmup_{abs(run_index):02d}" if run_index < 0 else f"run_{run_index:02d}" - ) - run_name = f"{scenario.name}_{run_label}" - timer = TimingRun( - project=wandb_project, - entity=wandb_entity, - mode=wandb_mode, - run_name=run_name, - group=scenario.group, - config={ - "scenario_id": scenario.scenario_id, - "scenario_name": scenario.name, - "question": scenario.question, - "model_id": model_id, - "workload_group": scenario.group, - "source_file": scenario.source_file, - "source_type": scenario.source_type, - "category": scenario.category, - "deterministic": scenario.deterministic, - }, - tags=[scenario.group, "timing-benchmark"], - ) - - with timer.phase("question_to_answer"): - result = await runner.run(scenario.question, timer=timer) - - failure_reasons = _classify_failure(result, result.plan) - success = len(failure_reasons) == 0 - failure_reason = " | ".join(failure_reasons) if failure_reasons else None - server_sequence = [step.agent for step in result.history] - - summary = timer.finish( - extra_metrics={ - "scenario_id": scenario.scenario_id, - "scenario_name": scenario.name, - "scenario_text": scenario.question, - "source_file": scenario.source_file, - "source_type": scenario.source_type, - "category": scenario.category or "", - "deterministic": ( - "" if scenario.deterministic is None else scenario.deterministic - ), - "success": success, - "failure_reason": failure_reason or "", - "question_length_chars": len(scenario.question), - "plan_steps": len(result.plan.steps), - "tool_calls": sum( - 1 - for step in result.history - if step.tool and step.tool.lower() not in ("none", "null", "") - ), - "server_sequence": ",".join(server_sequence), - "unique_servers": ",".join(sorted(set(server_sequence))), - }, - summary_path=str(output_dir / "runs" / f"{run_name}.json"), - ) - - return summary.to_dict(), success, failure_reason - - -def _describe(values: list[float]) -> dict[str, float | int]: - if not values: - return {"count": 0, "mean": 0.0, "std": 0.0, "min": 0.0, "max": 0.0} - std = statistics.stdev(values) if len(values) > 1 else 0.0 - return { - "count": len(values), - "mean": round(statistics.mean(values), 6), - "std": round(std, 6), - "min": round(min(values), 6), - "max": round(max(values), 6), - } - - -def _aggregate_runs(run_summaries: list[dict[str, Any]]) -> dict[str, Any]: - grouped: dict[str, list[dict[str, Any]]] = defaultdict(list) - for summary in run_summaries: - grouped[summary["group"]].append(summary) - - aggregate: dict[str, Any] = {"groups": {}, "overall": {}} - - all_total_times = [s["total_wall_time_seconds"] for s in run_summaries] - aggregate["overall"]["total_wall_time_seconds"] = _describe(all_total_times) - all_phase_names = sorted( - {phase for summary in run_summaries for phase in summary["phases"].keys()} - ) - aggregate["overall"]["phases"] = {} - for phase_name in all_phase_names: - phase_values = [ - float(summary["phases"][phase_name]["total_seconds"]) - for summary in run_summaries - if phase_name in summary["phases"] - ] - aggregate["overall"]["phases"][phase_name] = _describe(phase_values) - - for group, summaries in sorted(grouped.items()): - phase_names = sorted( - {phase for summary in summaries for phase in summary["phases"].keys()} - ) - group_total_times = [s["total_wall_time_seconds"] for s in summaries] - group_result: dict[str, Any] = { - "num_runs": len(summaries), - "total_wall_time_seconds": _describe(group_total_times), - "phases": {}, - "scenarios": sorted({s["metadata"]["scenario_name"] for s in summaries}), - "scenario_ids": sorted({int(s["metadata"]["scenario_id"]) for s in summaries}), - } - for phase_name in phase_names: - phase_values = [ - float(summary["phases"][phase_name]["total_seconds"]) - for summary in summaries - if phase_name in summary["phases"] - ] - group_result["phases"][phase_name] = _describe(phase_values) - aggregate["groups"][group] = group_result - - return aggregate - - -async def _main(args: argparse.Namespace) -> None: - output_dir = Path(args.output_dir) - output_dir.mkdir(parents=True, exist_ok=True) - - measured_runs: list[dict[str, Any]] = [] - dropped_runs: list[dict[str, Any]] = [] - scenarios = _load_scenarios() - - for scenario in scenarios: - print(f"Scenario: {scenario.name} [{scenario.group}]") - max_warmup_attempts = max(1, args.warmup_runs * args.max_attempts_multiplier) - warmups_completed = 0 - warmup_attempt = 0 - - while ( - warmups_completed < args.warmup_runs - and warmup_attempt < max_warmup_attempts - ): - warmup_attempt += 1 - print( - f" Warmup {warmups_completed + 1}/{args.warmup_runs} " - f"(attempt {warmup_attempt})" - ) - summary, success, failure_reason = await _run_scenario_once( - scenario=scenario, - model_id=args.model_id, - output_dir=output_dir, - wandb_project=args.wandb_project, - wandb_entity=args.wandb_entity, - wandb_mode=args.wandb_mode, - run_index=-(warmups_completed + 1), - ) - if success: - warmups_completed += 1 - await asyncio.sleep(args.inter_run_delay_seconds) - else: - dropped_runs.append(summary) - print(f" Dropped warmup run: {failure_reason}") - await asyncio.sleep(args.retry_delay_seconds) - - if warmups_completed < args.warmup_runs: - print(" Unable to complete requested warmup runs; moving on.") - - max_measured_attempts = max( - 1, args.measured_runs * args.max_attempts_multiplier - ) - measured_completed = 0 - measured_attempt = 0 - - while ( - measured_completed < args.measured_runs - and measured_attempt < max_measured_attempts - ): - measured_attempt += 1 - print( - f" Measured {measured_completed + 1}/{args.measured_runs} " - f"(attempt {measured_attempt})" - ) - summary, success, failure_reason = await _run_scenario_once( - scenario=scenario, - model_id=args.model_id, - output_dir=output_dir, - wandb_project=args.wandb_project, - wandb_entity=args.wandb_entity, - wandb_mode=args.wandb_mode, - run_index=measured_completed + 1, - ) - if success: - measured_runs.append(summary) - measured_completed += 1 - await asyncio.sleep(args.inter_run_delay_seconds) - else: - dropped_runs.append(summary) - print(f" Dropped measured run: {failure_reason}") - await asyncio.sleep(args.retry_delay_seconds) - - if measured_completed < args.measured_runs: - print(" Unable to complete requested measured runs for this scenario.") - - aggregate = _aggregate_runs(measured_runs) - (output_dir / "aggregate.json").write_text(json.dumps(aggregate, indent=2)) - (output_dir / "dropped_runs.json").write_text(json.dumps(dropped_runs, indent=2)) - - print(f"\nSaved aggregate timing summary to {output_dir / 'aggregate.json'}") - print(f"Saved dropped run details to {output_dir / 'dropped_runs.json'}") - - -def main() -> None: - load_dotenv() - args = _build_parser().parse_args() - asyncio.run(_main(args)) - - -if __name__ == "__main__": - main() diff --git a/src/servers/iot/main.py b/src/servers/iot/main.py index c1c2eefd8..038b7fc1a 100644 --- a/src/servers/iot/main.py +++ b/src/servers/iot/main.py @@ -114,16 +114,22 @@ def get_sensor_list(asset_id: str) -> List[str]: @mcp.tool() def sites() -> SitesResult: """Retrieves a list of sites. Each site is represented by a name.""" - return SitesResult(sites=SITES) + temp = SitesResult(sites=SITES) + logger.info(f"Sites result: {temp}") + return temp @mcp.tool() def assets(site_name: str) -> Union[AssetsResult, ErrorResult]: """Returns a list of assets for a given site. Each asset includes an id and a name.""" if site_name not in SITES: + logger.error(f"Unknown site requested: {site_name}") return ErrorResult(error=f"unknown site {site_name}") + logger.info(f"Assets called with site_name: {site_name}") + asset_list = get_asset_list() + logger.info(f"Assets found for site {site_name}: {asset_list}") return AssetsResult( site_name=site_name, total_assets=len(asset_list), @@ -135,13 +141,14 @@ def assets(site_name: str) -> Union[AssetsResult, ErrorResult]: @mcp.tool() def sensors(site_name: str, asset_id: str) -> Union[SensorsResult, ErrorResult]: """Lists the sensors available for a specified asset at a given site.""" + logger.info(f"Sensors called with site_name: {site_name}, asset_id: {asset_id}") if site_name not in SITES: + logger.error(f"Unknown site requested: {site_name}") return ErrorResult(error=f"unknown site {site_name}") - sensor_list = get_sensor_list(asset_id) if not sensor_list: + logger.error(f"Unknown asset ID requested: {asset_id}") return ErrorResult(error=f"unknown asset_id {asset_id} or no sensors found") - return SensorsResult( site_name=site_name, asset_id=asset_id, diff --git a/src/workflow/executor.py b/src/workflow/executor.py index efdceb8ca..604ebf6b4 100644 --- a/src/workflow/executor.py +++ b/src/workflow/executor.py @@ -6,7 +6,7 @@ executor makes a targeted LLM call to resolve the concrete values from the prior step's result, then calls the tool. -LLM call budget per question: +LLM call budget per question (approximate): - Independent steps (no placeholders): 0 extra LLM calls — tool called directly. - Dependent steps (has {{step_N}}): 1 LLM call to resolve args, then call tool. """ @@ -37,7 +37,8 @@ "TSFMAgent": "tsfm-mcp-server", } -_PLACEHOLDER_RE = re.compile(r"\{step_(\d+)\}") +# Match {step_1}, {step_1[0]}, etc. (LLMs often emit index hints like [0] for "first item".) +_PLACEHOLDER_RE = re.compile(r"\{step_(\d+)(?:\[[^\]]*\])?\}") _ARG_RESOLUTION_PROMPT = """\ You are resolving tool argument values for one step in a multi-step plan. @@ -51,11 +52,22 @@ The following arguments need their values resolved from the context above: {unresolved} -Respond with a JSON object containing ONLY the resolved argument values. +Respond with a JSON object containing ONLY the resolved argument for the unresolved parameters values for the tool call. Example: {{"site_name": "MAIN", "asset_id": "CH-1"}} Response:""" +CONTEXT_AGENT_NAME = "ContextAgent" + +_NO_TOOL_LLM_PROMPT = """Context: +{context} + +Task: {task} +Question: {question} + +Reply with one line only — the answer value (no sentences, no quotes around the whole reply). +""" + class Executor: """Executes plan steps by routing tool calls to MCP servers.""" @@ -115,18 +127,25 @@ async def execute_step( """Execute a single plan step. 1. Resolve the MCP server assigned to this step. - 2. If no tool is specified, return expected_output directly. + 2. If no tool is specified, parse prior JSON when possible; else one-line LLM. 3. If tool_args contain {{step_N}} placeholders, call the LLM to resolve them from prior step results. 4. Call the tool and return its result. """ if not step.tool or step.tool.lower() in ("none", "null"): + response = _answer_no_tool_step( + task=step.task, + question=question, + context=context, + dependency_steps=step.dependencies, + llm=self._llm, + ) return StepResult( step_number=step.step_number, task=step.task, - agent=step.agent, - response=step.expected_output, + agent=CONTEXT_AGENT_NAME, + response=response, tool=step.tool, tool_args=step.tool_args, ) @@ -144,8 +163,6 @@ async def execute_step( ), ) - - try: if _has_placeholders(step.tool_args): _log.info( @@ -159,6 +176,7 @@ async def execute_step( resolved_args = step.tool_args response = await _call_tool(server_path, step.tool, resolved_args) + print(f"Response for step {step.step_number}: {response}") return StepResult( step_number=step.step_number, task=step.task, @@ -266,6 +284,83 @@ def _parse_json(raw: str) -> dict: return {} +def _first_answer_line(text: str) -> str: + line = text.strip().splitlines()[0] if text.strip() else "" + return line.strip().strip('"').strip("'") + + +def _parse_json_object(raw: str) -> dict | None: + data = _parse_json(raw) + return data if data else None + + +def _asset_ids_from_payload(data: dict) -> list[str]: + assets = data.get("assets") + if not isinstance(assets, list): + return [] + ids: list[str] = [] + for x in assets: + if isinstance(x, str) and x: + ids.append(x) + elif isinstance(x, dict): + for key in ("id", "name", "asset_id"): + v = x.get(key) + if isinstance(v, str) and v: + ids.append(v) + break + return ids + + +def _try_answer_from_assets_json( + task: str, + question: str, + context: dict[int, StepResult], + dependency_steps: list[int], +) -> str | None: + """If a dependency step is assets JSON, pick the asset id string without an LLM.""" + haystack = f"{task} {question}" + for n in sorted(dependency_steps, reverse=True): + if n not in context: + continue + data = _parse_json_object(context[n].response) + if not data: + continue + ids = _asset_ids_from_payload(data) + if not ids: + continue + if len(ids) == 1: + return ids[0] + for aid in ids: + if aid in haystack: + return aid + return None + + +def _format_dep_context(context: dict[int, StepResult], dependency_steps: list[int]) -> str: + lines = [ + f"Step {n}: {context[n].response}" + for n in sorted(dependency_steps) + if n in context + ] + return "\n".join(lines) if lines else "(no prior steps)" + + +def _answer_no_tool_step( + task: str, + question: str, + context: dict[int, StepResult], + dependency_steps: list[int], + llm: LLMBackend, +) -> str: + """Resolve tool-less steps: prefer parsing IoT ``assets`` JSON, else minimal LLM.""" + hit = _try_answer_from_assets_json(task, question, context, dependency_steps) + if hit is not None: + return hit + block = _format_dep_context(context, dependency_steps) + prompt = _NO_TOOL_LLM_PROMPT.format(context=block, task=task, question=question) + return _first_answer_line(llm.generate(prompt)) + + # ── MCP protocol helpers ────────────────────────────────────────────────────── @@ -337,6 +432,7 @@ async def _call_tool(server_path: Path | str, tool_name: str, args: dict) -> str async with ClientSession(read, write) as session: await session.initialize() result = await session.call_tool(tool_name, args) + print(f"Result for tool {tool_name} with args {args}: {result}") return _extract_content(result.content) diff --git a/src/workflow/planner.py b/src/workflow/planner.py index b787ab0e5..c6d2f2b42 100644 --- a/src/workflow/planner.py +++ b/src/workflow/planner.py @@ -46,6 +46,8 @@ - Use {{step_N}} as a placeholder when an argument depends on step N's result. - Dependencies use #S notation (e.g., #S1, #S2). Use "None" if none. - Keep tasks specific and actionable. +- For Tool "none" steps that list dependencies, #ExpectedOutput describes the artifact + to derive; the runtime extracts concrete values from prior results (not literal text). Question: {question} diff --git a/src/workflow/tests/test_runner.py b/src/workflow/tests/test_runner.py index 0246633a9..ff71ecca9 100644 --- a/src/workflow/tests/test_runner.py +++ b/src/workflow/tests/test_runner.py @@ -122,7 +122,7 @@ async def test_orchestrator_unknown_agent_recorded_as_error(sequential_llm): @pytest.mark.anyio async def test_orchestrator_no_tool_returns_expected_output(sequential_llm): - """A step with tool=none returns expected_output directly (no MCP call).""" + """A step with tool=none and no dependencies returns expected_output (no MCP call).""" plan_with_no_tool = ( "#Task1: Answer from context\n" "#Agent1: IoTAgent\n" From a524ed626e8abe70be75156805a91b820bbc2739 Mon Sep 17 00:00:00 2001 From: Darief Maes Date: Sun, 10 May 2026 16:52:02 -0400 Subject: [PATCH 3/3] caching code --- .../fmsr_utterance_cache_comparison.svg | 216 ++++ .../timing/fmsr_utterance_cached_heatmap.svg | 171 +++ .../timing/fmsr_utterance_plan_execute.json | 988 ++++++++++++++++++ plot_timing_heatmap.py | 313 ++++++ src/cache/cache.py | 80 ++ src/servers/fmsr/cache.json | 1 + src/servers/fmsr/main.py | 41 +- src/servers/iot/cache.json | 1 + src/servers/iot/main.py | 17 +- src/workflow/__init__.py | 8 + src/workflow/executor.py | 2 - src/workflow/tests/test_timing.py | 58 + src/workflow/timing.py | 734 +++++++++++++ time_fmsr_utterance.py | 197 ++++ 14 files changed, 2813 insertions(+), 14 deletions(-) create mode 100644 artifacts/timing/fmsr_utterance_cache_comparison.svg create mode 100644 artifacts/timing/fmsr_utterance_cached_heatmap.svg create mode 100644 artifacts/timing/fmsr_utterance_plan_execute.json create mode 100644 plot_timing_heatmap.py create mode 100644 src/cache/cache.py create mode 100644 src/servers/fmsr/cache.json create mode 100644 src/servers/iot/cache.json create mode 100644 src/workflow/tests/test_timing.py create mode 100644 time_fmsr_utterance.py diff --git a/artifacts/timing/fmsr_utterance_cache_comparison.svg b/artifacts/timing/fmsr_utterance_cache_comparison.svg new file mode 100644 index 000000000..030d845ae --- /dev/null +++ b/artifacts/timing/fmsr_utterance_cache_comparison.svg @@ -0,0 +1,216 @@ + + + + +Mean wall time by cache mode (lower = faster) +No cache +Cache +101 + +16.4s + +10.1s +102 + +10.2s + +14.7s +103 + +12.8s + +36.9s +104 + +16.0s + +16.8s +105 + +15.0s + +12.3s +106 + +17.5s + +19.6s +107 + +42.1s + +239.8s +108 + +469.8s + +265.7s +109 + +591.5s + +330.3s +110 + +27.5s + +26.3s +111 + +893.2s + +802.2s +112 + +436.0s + +168.2s +113 + +70.8s + +27.2s +114 + +251.2s + +292.4s +115 + +59.7s + +25.0s +116 + +507.2s + +283.0s +117 + +38.8s + +436.5s +118 + +182.8s + +61.1s +119 + +52.7s + +327.2s +120 + +317.4s + +55.5s +121 + +260.5s + +352.7s +122 + +548.2s + +391.2s + +Scenario ID +Cache mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +10 + +452 + +893 + +Mean wall time (s) + \ No newline at end of file diff --git a/artifacts/timing/fmsr_utterance_cached_heatmap.svg b/artifacts/timing/fmsr_utterance_cached_heatmap.svg new file mode 100644 index 000000000..2680f4fbe --- /dev/null +++ b/artifacts/timing/fmsr_utterance_cached_heatmap.svg @@ -0,0 +1,171 @@ + + + + +Wall time heatmap with caching (lower = faster) +Cached +101 + +11.6s +102 + +14.4s +103 + +9.6s +104 + +17.2s +105 + +14.9s +106 + +16.5s +107 + +624.9s +108 + +26.0s +109 + +29.4s +110 + +63.4s +111 + +101.5s +112 + +26.7s +113 + +26.2s +114 + +15.8s +115 + +114.5s +116 + +25.3s +117 + +48.9s +118 + +53.9s +119 + +29.7s +120 + +24.0s +121 + +35.5s +122 + +32.5s + +Scenario ID +Cached + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +10 + +317 + +625 + +Wall time (s) + \ No newline at end of file diff --git a/artifacts/timing/fmsr_utterance_plan_execute.json b/artifacts/timing/fmsr_utterance_plan_execute.json new file mode 100644 index 000000000..aa2fbd28d --- /dev/null +++ b/artifacts/timing/fmsr_utterance_plan_execute.json @@ -0,0 +1,988 @@ +{ + "scenario_path": "/Users/dariefmaes/Downloads/AssetOpsBench/src/tmp/meta_agent/scenarios/single_agent/fmsr_utterance.json", + "scenario_count": 22, + "successful": 22, + "failed": 0, + "total_wall_time_seconds": 1362.685039, + "hardware": { + "sampler": "resource", + "sample_count": 3914, + "cpu_percent_average": 0.279532, + "cpu_percent_peak": 77.508974, + "memory_rss_bytes_average": 235085104, + "memory_rss_bytes_peak": 235470848, + "process_cpu_time_seconds": 5.355271, + "child_cpu_time_seconds": 105.163643, + "child_max_rss_bytes": 241385472 + }, + "scenarios": [ + { + "id": 101, + "type": "FMSR", + "deterministic": true, + "question": "List all failure modes of asset Chiller.", + "success": true, + "wall_time_seconds": 11.641885, + "phases": { + "discover": { + "count": 1, + "total_seconds": 2.450611, + "average_seconds": 2.450611 + }, + "execute": { + "count": 1, + "total_seconds": 1.737178, + "average_seconds": 1.737178 + }, + "plan": { + "count": 1, + "total_seconds": 6.325359, + "average_seconds": 6.325359 + }, + "summarise": { + "count": 1, + "total_seconds": 1.127545, + "average_seconds": 1.127545 + } + }, + "hardware": { + "sampler": "resource", + "sample_count": 17, + "cpu_percent_average": 6.533879, + "cpu_percent_peak": 77.50723, + "memory_rss_bytes_average": 146658967, + "memory_rss_bytes_peak": 235470848, + "process_cpu_time_seconds": 1.187057, + "child_cpu_time_seconds": 3.260576, + "child_max_rss_bytes": 118538240 + }, + "plan_steps": 4, + "tool_calls": 3, + "answer": "The failure modes of asset \"Chiller\" are:\n1. Compressor Overheating: Failed due to Normal wear, overheating\n2. Heat Exchangers: Fans: Degraded motor or worn bearing due to Normal use\n3. Evaporator Water side fouling\n4. Condenser Water side fouling\n5. Condenser Improper water side flow rate\n6. Purge Unit Excessive purge\n7. Refrigerant Operated Control Valve Failed spring" + }, + { + "id": 102, + "type": "FMSR", + "deterministic": true, + "question": "List all failure modes of asset Chiller 6.", + "success": true, + "wall_time_seconds": 14.395841, + "phases": { + "discover": { + "count": 1, + "total_seconds": 1.950699, + "average_seconds": 1.950699 + }, + "execute": { + "count": 1, + "total_seconds": 1.584653, + "average_seconds": 1.584653 + }, + "plan": { + "count": 1, + "total_seconds": 5.405885, + "average_seconds": 5.405885 + }, + "summarise": { + "count": 1, + "total_seconds": 5.452048, + "average_seconds": 5.452048 + } + }, + "hardware": { + "sampler": "resource", + "sample_count": 15, + "cpu_percent_average": 7.331336, + "cpu_percent_peak": 93.980701, + "memory_rss_bytes_average": 235470848, + "memory_rss_bytes_peak": 235470848, + "process_cpu_time_seconds": 0.074831, + "child_cpu_time_seconds": 3.062343, + "child_max_rss_bytes": 118538240 + }, + "plan_steps": 4, + "tool_calls": 3, + "answer": "To provide a concise and direct answer, let's analyze the given information and execution results.\n\n1. The task was to list all failure modes of asset \"Chiller 6\".\n2. The steps involved identifying the site, finding assets at that site, identifying \"Chiller 6\", and then retrieving its failure modes.\n3. The relevant output from the steps is:\n - The assets at site \"MAIN\" were identified in Step 2 and referenced in Step 3.\n - The asset \"Chiller 6\" was found among the assets at \"MAIN\" (implied by Step 3).\n - Step 4 aimed to retrieve the failure modes for \"Chiller 6\" using the FMSRAgent.\n\nSince the actual output of `get_failure_modes(asset_name=\"Chiller 6\")` is not provided due to being marked as an \"Unknown tool,\" we can't directly list the failure modes. However, for the sake of providing a final answer based on the structure given:\n\nIf the `get_failure_modes(asset_name=\"Chiller 6\")` tool was successfully executed, it would return a list of failure modes associated with \"Chiller 6\". \n\nLet's hypothetically say the output was: \n```json\n[\n \"Failure Mode 1: Loss of Cooling Capacity\",\n \"Failure Mode 2: Compressor Failure\",\n \"Failure Mode 3: Leaks in the System\"\n]\n```\n\nThe final answer to the original question, \"List all failure modes of asset Chiller 6,\" would be:\n\nThe failure modes for \"Chiller 6\" are:\n1. Loss of Cooling Capacity\n2. Compressor Failure\n3. Leaks in the System\n\nPlease note that this is a hypothetical answer as the actual output from the `get_failure_modes` tool is not available. In a real scenario, you would replace this with the actual output from the tool." + }, + { + "id": 103, + "type": "FMSR", + "deterministic": false, + "question": "List all failure modes of asset Wind Turbine.", + "success": true, + "wall_time_seconds": 9.636652, + "phases": { + "discover": { + "count": 1, + "total_seconds": 1.939931, + "average_seconds": 1.939931 + }, + "execute": { + "count": 1, + "total_seconds": 5.240937, + "average_seconds": 5.240937 + }, + "plan": { + "count": 1, + "total_seconds": 1.219172, + "average_seconds": 1.219172 + }, + "summarise": { + "count": 1, + "total_seconds": 1.235299, + "average_seconds": 1.235299 + } + }, + "hardware": { + "sampler": "resource", + "sample_count": 30, + "cpu_percent_average": 3.965051, + "cpu_percent_peak": 98.784015, + "memory_rss_bytes_average": 235470848, + "memory_rss_bytes_peak": 235470848, + "process_cpu_time_seconds": 0.068751, + "child_cpu_time_seconds": 3.275595, + "child_max_rss_bytes": 234389504 + }, + "plan_steps": 1, + "tool_calls": 1, + "answer": "The failure modes of the asset \"Wind Turbine\" are: \n1. Blade Failure\n2. Gearbox Failure\n3. Bearing Failure\n4. Generator Failure\n5. Control System Failure\n6. Pitch System Failure\n7. Yaw System Failure\n8. Foundation Failure\n9. Tower Failure\n10. Electrical System Failure\n11. Hydraulic System Failure\n12. Brake System Failure\n13. Rotor Hub Failure\n14. Main Shaft Failure\n15. Lightning Strike Damage." + }, + { + "id": 104, + "type": "FMSR", + "deterministic": false, + "question": "List all installed sensors of asset Chiller.", + "success": true, + "wall_time_seconds": 17.173927, + "phases": { + "discover": { + "count": 1, + "total_seconds": 2.086322, + "average_seconds": 2.086322 + }, + "execute": { + "count": 1, + "total_seconds": 4.874134, + "average_seconds": 4.874134 + }, + "plan": { + "count": 1, + "total_seconds": 9.077082, + "average_seconds": 9.077082 + }, + "summarise": { + "count": 1, + "total_seconds": 1.131057, + "average_seconds": 1.131057 + } + }, + "hardware": { + "sampler": "resource", + "sample_count": 17, + "cpu_percent_average": 6.268233, + "cpu_percent_peak": 91.713831, + "memory_rss_bytes_average": 235470848, + "memory_rss_bytes_peak": 235470848, + "process_cpu_time_seconds": 0.099856, + "child_cpu_time_seconds": 3.274091, + "child_max_rss_bytes": 234389504 + }, + "plan_steps": 4, + "tool_calls": 3, + "answer": "The task to list all installed sensors of asset \"Chiller\" failed due to an error in the \"List the sensors for 'Chiller'\" step. The error message indicates that both \"site_name\" and \"asset_id\" fields are required but were missing. Although the asset ID was identified as \"Chiller 6\", it appears the information was not correctly passed to the subsequent step. Therefore, the list of installed sensors for \"Chiller\" could not be determined." + }, + { + "id": 105, + "type": "FMSR", + "deterministic": true, + "question": "List all installed sensors of asset Chiller 6.", + "success": true, + "wall_time_seconds": 14.916983, + "phases": { + "discover": { + "count": 1, + "total_seconds": 2.025526, + "average_seconds": 2.025526 + }, + "execute": { + "count": 1, + "total_seconds": 3.906173, + "average_seconds": 3.906173 + }, + "plan": { + "count": 1, + "total_seconds": 7.432716, + "average_seconds": 7.432716 + }, + "summarise": { + "count": 1, + "total_seconds": 1.551219, + "average_seconds": 1.551219 + } + }, + "hardware": { + "sampler": "resource", + "sample_count": 23, + "cpu_percent_average": 4.701852, + "cpu_percent_peak": 85.415639, + "memory_rss_bytes_average": 235470848, + "memory_rss_bytes_peak": 235470848, + "process_cpu_time_seconds": 0.109527, + "child_cpu_time_seconds": 3.46193, + "child_max_rss_bytes": 234389504 + }, + "plan_steps": 4, + "tool_calls": 3, + "answer": "The installed sensors for asset \"Chiller 6\" are:\n1. Chiller 6 Chiller % Loaded\n2. Chiller 6 Chiller Efficiency\n3. Chiller 6 Condenser Water Flow\n4. Chiller 6 Condenser Water Return To Tower Temperature\n5. Chiller 6 Liquid Refrigerant Evaporator Temperature\n6. Chiller 6 Power Input\n7. Chiller 6 Return Temperature\n8. Chiller 6 Schedule\n9. Chiller 6 Setpoint Temperature\n10. Chiller 6 Supply Temperature\n11. Chiller 6 Tonnage\n\nThere are 11 sensors in total." + }, + { + "id": 106, + "type": "FMSR", + "deterministic": false, + "question": "List all installed sensors of asset Wind Turbine.", + "success": true, + "wall_time_seconds": 16.496821, + "phases": { + "discover": { + "count": 1, + "total_seconds": 2.146798, + "average_seconds": 2.146798 + }, + "execute": { + "count": 1, + "total_seconds": 3.108658, + "average_seconds": 3.108658 + }, + "plan": { + "count": 1, + "total_seconds": 10.353155, + "average_seconds": 10.353155 + }, + "summarise": { + "count": 1, + "total_seconds": 0.887104, + "average_seconds": 0.887104 + } + }, + "hardware": { + "sampler": "resource", + "sample_count": 21, + "cpu_percent_average": 5.669804, + "cpu_percent_peak": 94.290226, + "memory_rss_bytes_average": 235470848, + "memory_rss_bytes_peak": 235470848, + "process_cpu_time_seconds": 0.130589, + "child_cpu_time_seconds": 3.504184, + "child_max_rss_bytes": 234389504 + }, + "plan_steps": 3, + "tool_calls": 3, + "answer": "There are no sensors found for the asset \"Wind Turbine\". The asset ID for \"Wind Turbine\" at site \"MAIN\" was not found; instead, \"Chiller 6\" was listed as the asset. Attempts to list sensors for \"Wind Turbine\" directly resulted in an \"unknown asset_id or no sensors found\" error." + }, + { + "id": 107, + "type": "FMSR", + "deterministic": false, + "question": "List all failure modes of Chiller 6 that can be detected by Chiller 6 Chiller Efficiency.", + "success": true, + "wall_time_seconds": 624.85251, + "phases": { + "discover": { + "count": 1, + "total_seconds": 2.023912, + "average_seconds": 2.023912 + }, + "execute": { + "count": 1, + "total_seconds": 611.967719, + "average_seconds": 611.967719 + }, + "plan": { + "count": 1, + "total_seconds": 8.97365, + "average_seconds": 8.97365 + }, + "summarise": { + "count": 1, + "total_seconds": 1.884733, + "average_seconds": 1.884733 + } + }, + "hardware": { + "sampler": "resource", + "sample_count": 2424, + "cpu_percent_average": 0.17449, + "cpu_percent_peak": 75.13038, + "memory_rss_bytes_average": 235470848, + "memory_rss_bytes_peak": 235470848, + "process_cpu_time_seconds": 0.970683, + "child_cpu_time_seconds": 5.284165, + "child_max_rss_bytes": 234389504 + }, + "plan_steps": 6, + "tool_calls": 5, + "answer": "The failure modes of Chiller 6 that can be detected by 'Chiller 6 Chiller Efficiency' could not be determined due to an error in mapping failure modes to the 'Chiller Efficiency' sensor. However, the identified failure modes for Chiller 6 are: \n1. Compressor Overheating: Failed due to Normal wear, overheating\n2. Heat Exchangers: Fans: Degraded motor or worn bearing due to Normal use\n3. Evaporator Water side fouling\n4. Condenser Water side fouling\n5. Condenser Improper water side flow rate\n6. Purge Unit Excessive purge\n7. Refrigerant Operated Control Valve Failed spring\n\nFurther investigation is required to accurately map these failure modes to 'Chiller 6 Chiller Efficiency'." + }, + { + "id": 108, + "type": "FMSR", + "deterministic": false, + "question": "List all failure modes of Chiller 6 that can be detected by temperature sensors.", + "success": true, + "wall_time_seconds": 26.039467, + "phases": { + "discover": { + "count": 1, + "total_seconds": 2.200262, + "average_seconds": 2.200262 + }, + "execute": { + "count": 1, + "total_seconds": 15.13843, + "average_seconds": 15.13843 + }, + "plan": { + "count": 1, + "total_seconds": 7.964879, + "average_seconds": 7.964879 + }, + "summarise": { + "count": 1, + "total_seconds": 0.73291, + "average_seconds": 0.73291 + } + }, + "hardware": { + "sampler": "resource", + "sample_count": 42, + "cpu_percent_average": 2.95073, + "cpu_percent_peak": 97.075612, + "memory_rss_bytes_average": 235470848, + "memory_rss_bytes_peak": 235470848, + "process_cpu_time_seconds": 0.145352, + "child_cpu_time_seconds": 5.183131, + "child_max_rss_bytes": 237502464 + }, + "plan_steps": 7, + "tool_calls": 5, + "answer": "The failure modes of Chiller 6 that can be detected by temperature sensors are: Chiller malfunction, Cooling coil fouling, Faulty thermostat, Sensor failure, Refrigerant leak, Clogged air filter, Improper chiller operation, Cooling system failure." + }, + { + "id": 109, + "type": "FMSR", + "deterministic": false, + "question": "List all failure modes of Chiller 6 that can be detected by temperature sensors and power input sensors.", + "success": true, + "wall_time_seconds": 29.410461, + "phases": { + "discover": { + "count": 1, + "total_seconds": 1.954369, + "average_seconds": 1.954369 + }, + "execute": { + "count": 1, + "total_seconds": 17.676295, + "average_seconds": 17.676295 + }, + "plan": { + "count": 1, + "total_seconds": 5.606803, + "average_seconds": 5.606803 + }, + "summarise": { + "count": 1, + "total_seconds": 4.171393, + "average_seconds": 4.171393 + } + }, + "hardware": { + "sampler": "resource", + "sample_count": 22, + "cpu_percent_average": 5.443137, + "cpu_percent_peak": 96.333564, + "memory_rss_bytes_average": 235470848, + "memory_rss_bytes_peak": 235470848, + "process_cpu_time_seconds": 0.159555, + "child_cpu_time_seconds": 4.047698, + "child_max_rss_bytes": 237502464 + }, + "plan_steps": 8, + "tool_calls": 5, + "answer": "The task to list all failure modes of Chiller 6 detectable by temperature sensors and power input sensors was not completed due to an error in Step 7. However, based on the available information:\n\nThe relevant sensors for Chiller 6 are:\n- Temperature sensors: \"Chiller 6 Condenser Water Return To Tower Temperature\", \"Chiller 6 Liquid Refrigerant Evaporator Temperature\", \"Chiller 6 Return Temperature\", \"Chiller 6 Supply Temperature\", \"Chiller 6 Setpoint Temperature\"\n- Power input sensor: \"Chiller 6 Power Input\"\n\nThe failure modes for Chiller 6 are:\n1. Compressor Overheating: Failed due to Normal wear, overheating\n2. Heat Exchangers: Fans: Degraded motor or worn bearing due to Normal use\n3. Evaporator Water side fouling\n4. Condenser Water side fouling\n5. Condenser Improper water side flow rate\n6. Purge Unit Excessive purge\n7. Refrigerant Operated Control Valve Failed spring\n\nWithout the correct mapping between failure modes and sensors, we cannot directly list the failure modes detectable by the specified sensors. However, we can infer that certain failure modes are likely detectable:\n- \"Compressor Overheating\" might be detectable by temperature sensors.\n- \"Evaporator Water side fouling\" and \"Condenser Water side fouling\" could be related to temperature changes, thus potentially detectable by temperature sensors.\n- \"Compressor Overheating\" and other mechanical issues might be associated with changes in \"Chiller 6 Power Input\".\n\nThe exact failure modes detectable by temperature and power input sensors cannot be conclusively determined due to the error in the execution." + }, + { + "id": 110, + "type": "FMSR", + "deterministic": false, + "question": "List all failure modes of Wind Turbine that can be detected by temperature sensors.", + "success": true, + "wall_time_seconds": 63.434274, + "phases": { + "discover": { + "count": 1, + "total_seconds": 1.980702, + "average_seconds": 1.980702 + }, + "execute": { + "count": 1, + "total_seconds": 55.559173, + "average_seconds": 55.559173 + }, + "plan": { + "count": 1, + "total_seconds": 5.338041, + "average_seconds": 5.338041 + }, + "summarise": { + "count": 1, + "total_seconds": 0.554575, + "average_seconds": 0.554575 + } + }, + "hardware": { + "sampler": "resource", + "sample_count": 186, + "cpu_percent_average": 0.77433, + "cpu_percent_peak": 96.647286, + "memory_rss_bytes_average": 235470848, + "memory_rss_bytes_peak": 235470848, + "process_cpu_time_seconds": 0.201303, + "child_cpu_time_seconds": 5.7374, + "child_max_rss_bytes": 237502464 + }, + "plan_steps": 7, + "tool_calls": 4, + "answer": "The failure modes of a Wind Turbine that can be detected by temperature sensors are: Bearing failure, Electrical component failure, Gearbox failure, and Generator failure." + }, + { + "id": 111, + "type": "FMSR", + "deterministic": false, + "question": "Get failure modes for Chiller 6 and only include in final response those that can be monitored using the available sensors.", + "success": true, + "wall_time_seconds": 101.481954, + "phases": { + "discover": { + "count": 1, + "total_seconds": 1.908488, + "average_seconds": 1.908488 + }, + "execute": { + "count": 1, + "total_seconds": 91.376439, + "average_seconds": 91.376439 + }, + "plan": { + "count": 1, + "total_seconds": 5.568536, + "average_seconds": 5.568536 + }, + "summarise": { + "count": 1, + "total_seconds": 2.627066, + "average_seconds": 2.627066 + } + }, + "hardware": { + "sampler": "resource", + "sample_count": 334, + "cpu_percent_average": 0.504207, + "cpu_percent_peak": 95.483861, + "memory_rss_bytes_average": 235470848, + "memory_rss_bytes_peak": 235470848, + "process_cpu_time_seconds": 0.270432, + "child_cpu_time_seconds": 4.915514, + "child_max_rss_bytes": 237502464 + }, + "plan_steps": 7, + "tool_calls": 5, + "answer": "The task to provide the failure modes for Chiller 6 that can be monitored using the available sensors encountered an error in Step 6, which prevented the completion of the subsequent steps. Specifically, the error \"Object of type RelevancyEntry is not JSON serializable\" occurred while determining the mapping between failure modes and sensors.\n\nHowever, based on the information available up to Step 5, the failure modes for Chiller 6 are:\n1. Compressor Overheating: Failed due to Normal wear, overheating\n2. Heat Exchangers: Fans: Degraded motor or worn bearing due to Normal use\n3. Evaporator Water side fouling\n4. Condenser Water side fouling\n5. Condenser Improper water side flow rate\n6. Purge Unit Excessive purge\n7. Refrigerant Operated Control Valve Failed spring\n\nGiven the available sensors (listed in Step 4), it is not possible to directly conclude which failure modes can be monitored without the successful completion of Step 6. \n\nTherefore, the final answer to the original question cannot be accurately provided due to the error encountered during the execution." + }, + { + "id": 112, + "type": "FMSR", + "deterministic": false, + "question": "Are there any failure modes of Chiller 6 that can be predicted by monitoring the vibration sensor data?", + "success": true, + "wall_time_seconds": 26.696445, + "phases": { + "discover": { + "count": 1, + "total_seconds": 2.108974, + "average_seconds": 2.108974 + }, + "execute": { + "count": 1, + "total_seconds": 16.835913, + "average_seconds": 16.835913 + }, + "plan": { + "count": 1, + "total_seconds": 6.56143, + "average_seconds": 6.56143 + }, + "summarise": { + "count": 1, + "total_seconds": 1.18879, + "average_seconds": 1.18879 + } + }, + "hardware": { + "sampler": "resource", + "sample_count": 41, + "cpu_percent_average": 2.955887, + "cpu_percent_peak": 94.982588, + "memory_rss_bytes_average": 235470848, + "memory_rss_bytes_peak": 235470848, + "process_cpu_time_seconds": 0.162385, + "child_cpu_time_seconds": 4.985636, + "child_max_rss_bytes": 237502464 + }, + "plan_steps": 7, + "tool_calls": 5, + "answer": "Unfortunately, the results are inconclusive because Step 6 encountered an error (\"Object of type RelevancyEntry is not JSON serializable\") and did not provide the necessary mapping between failure modes and sensors. Therefore, it is not possible to determine if vibration sensor data can predict any failure modes of Chiller 6. Additionally, the list of sensors for Chiller 6 (from Step 4) does not explicitly include a vibration sensor." + }, + { + "id": 113, + "type": "FMSR", + "deterministic": false, + "question": "List all sensors of Chiller 6 that are potentially relevant to overheating.", + "success": true, + "wall_time_seconds": 26.217442, + "phases": { + "discover": { + "count": 1, + "total_seconds": 2.046627, + "average_seconds": 2.046627 + }, + "execute": { + "count": 1, + "total_seconds": 14.67489, + "average_seconds": 14.67489 + }, + "plan": { + "count": 1, + "total_seconds": 6.349971, + "average_seconds": 6.349971 + }, + "summarise": { + "count": 1, + "total_seconds": 3.144407, + "average_seconds": 3.144407 + } + }, + "hardware": { + "sampler": "resource", + "sample_count": 42, + "cpu_percent_average": 2.911564, + "cpu_percent_peak": 96.168867, + "memory_rss_bytes_average": 235470848, + "memory_rss_bytes_peak": 235470848, + "process_cpu_time_seconds": 0.142065, + "child_cpu_time_seconds": 5.130565, + "child_max_rss_bytes": 237502464 + }, + "plan_steps": 7, + "tool_calls": 5, + "answer": "The sensors of Chiller 6 that are potentially relevant to overheating are not explicitly identified due to an error in Step 6. However, based on the available information, the relevant sensors can be inferred from the list of sensors available for Chiller 6 and the failure modes related to overheating.\n\nThe available sensors for Chiller 6 are:\n\"Chiller 6 Chiller % Loaded\",\n\"Chiller 6 Chiller Efficiency\",\n\"Chiller 6 Condenser Water Flow\",\n\"Chiller 6 Condenser Water Return To Tower Temperature\",\n\"Chiller 6 Liquid Refrigerant Evaporator Temperature\",\n\"Chiller 6 Power Input\",\n\"Chiller 6 Return Temperature\",\n\"Chiller 6 Schedule\",\n\"Chiller 6 Setpoint Temperature\",\n\"Chiller 6 Supply Temperature\",\n\"Chiller 6 Tonnage\"\n\nThe failure mode related to overheating is \"Compressor Overheating: Failed due to Normal wear, overheating\".\n\nAlthough the direct mapping to relevant sensors failed, some sensors can be logically linked to overheating:\n- \"Chiller 6 Liquid Refrigerant Evaporator Temperature\"\n- \"Chiller 6 Condenser Water Return To Tower Temperature\"\n- \"Chiller 6 Supply Temperature\"\n- \"Chiller 6 Return Temperature\"\n- \"Chiller 6 Power Input\"\n\nThese sensors could be considered potentially relevant to monitoring overheating issues in Chiller 6." + }, + { + "id": 114, + "type": "FMSR", + "deterministic": false, + "question": " If compressor overheating occurs for Chiller 6, which sensor should be prioritized for monitoring this specific failure?", + "success": true, + "wall_time_seconds": 15.814637, + "phases": { + "discover": { + "count": 1, + "total_seconds": 2.026682, + "average_seconds": 2.026682 + }, + "execute": { + "count": 1, + "total_seconds": 5.639028, + "average_seconds": 5.639028 + }, + "plan": { + "count": 1, + "total_seconds": 6.999857, + "average_seconds": 6.999857 + }, + "summarise": { + "count": 1, + "total_seconds": 1.147969, + "average_seconds": 1.147969 + } + }, + "hardware": { + "sampler": "resource", + "sample_count": 20, + "cpu_percent_average": 5.610835, + "cpu_percent_peak": 91.775565, + "memory_rss_bytes_average": 235470848, + "memory_rss_bytes_peak": 235470848, + "process_cpu_time_seconds": 0.091849, + "child_cpu_time_seconds": 3.975054, + "child_max_rss_bytes": 237502464 + }, + "plan_steps": 6, + "tool_calls": 5, + "answer": "To monitor compressor overheating for Chiller 6, the Compressor Discharge Temperature Sensor should be prioritized. This is based on the information obtained during the task execution, specifically the asset id confirmation for Chiller 6 in Step 3, and the identification of \"Compressor Overheating\" as a known failure mode in Step 5. Although Step 6 encountered an error, the relevant sensor can be inferred from the available data." + }, + { + "id": 115, + "type": "FMSR", + "deterministic": false, + "question": "List all sensors of Wind Turbine that are potentially relevant to Improper water side flow rate.", + "success": true, + "wall_time_seconds": 114.460381, + "phases": { + "discover": { + "count": 1, + "total_seconds": 2.128545, + "average_seconds": 2.128545 + }, + "execute": { + "count": 1, + "total_seconds": 105.939722, + "average_seconds": 105.939722 + }, + "plan": { + "count": 1, + "total_seconds": 5.338427, + "average_seconds": 5.338427 + }, + "summarise": { + "count": 1, + "total_seconds": 1.052179, + "average_seconds": 1.052179 + } + }, + "hardware": { + "sampler": "resource", + "sample_count": 418, + "cpu_percent_average": 0.421872, + "cpu_percent_peak": 94.104746, + "memory_rss_bytes_average": 235470848, + "memory_rss_bytes_peak": 235470848, + "process_cpu_time_seconds": 0.293731, + "child_cpu_time_seconds": 6.794414, + "child_max_rss_bytes": 237502464 + }, + "plan_steps": 8, + "tool_calls": 5, + "answer": "There are no sensors listed for \"Wind Turbine\" that are potentially relevant to \"Improper water side flow rate\". The asset identified as \"Wind Turbine\" is actually \"Chiller 6\", and its sensors are related to chiller operations, not wind turbines. The failure mode \"Improper water side flow rate\" is not identified, and the sensors relevant to it could not be determined." + }, + { + "id": 116, + "type": "FMSR", + "deterministic": false, + "question": "What are the failure modes of Chiller 6 that can be identified by analyzing the data from the available sensors?", + "success": true, + "wall_time_seconds": 25.345322, + "phases": { + "discover": { + "count": 1, + "total_seconds": 2.181887, + "average_seconds": 2.181887 + }, + "execute": { + "count": 1, + "total_seconds": 14.979823, + "average_seconds": 14.979823 + }, + "plan": { + "count": 1, + "total_seconds": 6.278313, + "average_seconds": 6.278313 + }, + "summarise": { + "count": 1, + "total_seconds": 1.903366, + "average_seconds": 1.903366 + } + }, + "hardware": { + "sampler": "resource", + "sample_count": 42, + "cpu_percent_average": 2.891937, + "cpu_percent_peak": 94.627367, + "memory_rss_bytes_average": 235470848, + "memory_rss_bytes_peak": 235470848, + "process_cpu_time_seconds": 0.137754, + "child_cpu_time_seconds": 5.126573, + "child_max_rss_bytes": 241385472 + }, + "plan_steps": 6, + "tool_calls": 5, + "answer": "The failure modes of Chiller 6 that can be identified are not directly determinable due to an error in mapping the failure modes to the available sensors. However, the known failure modes for Chiller 6 are: \n1. Compressor Overheating: Failed due to Normal wear, overheating\n2. Heat Exchangers: Fans: Degraded motor or worn bearing due to Normal use\n3. Evaporator Water side fouling\n4. Condenser Water side fouling\n5. Condenser Improper water side flow rate\n6. Purge Unit Excessive purge\n7. Refrigerant Operated Control Valve Failed spring\n\nAvailable sensors for Chiller 6 include those measuring loaded percentage, efficiency, temperatures, flow, power input, and more. A successful mapping between these sensors and failure modes is required to conclusively identify detectable failure modes." + }, + { + "id": 117, + "type": "FMSR", + "deterministic": false, + "question": "Generate an anomaly detection recipe for detecting compressor motor failure for chiller.", + "success": true, + "wall_time_seconds": 48.878144, + "phases": { + "discover": { + "count": 1, + "total_seconds": 1.908737, + "average_seconds": 1.908737 + }, + "execute": { + "count": 1, + "total_seconds": 35.515178, + "average_seconds": 35.515178 + }, + "plan": { + "count": 1, + "total_seconds": 10.297725, + "average_seconds": 10.297725 + }, + "summarise": { + "count": 1, + "total_seconds": 1.155108, + "average_seconds": 1.155108 + } + }, + "hardware": { + "sampler": "resource", + "sample_count": 54, + "cpu_percent_average": 2.469756, + "cpu_percent_peak": 98.650581, + "memory_rss_bytes_average": 235470848, + "memory_rss_bytes_peak": 235470848, + "process_cpu_time_seconds": 0.20091, + "child_cpu_time_seconds": 6.938321, + "child_max_rss_bytes": 241385472 + }, + "plan_steps": 10, + "tool_calls": 8, + "answer": "Failed to generate an anomaly detection recipe for detecting compressor motor failure for the chiller due to errors in determining the mapping between failure modes and sensors, and subsequent issues with running time-series forecasting and anomaly detection. The available sensors for \"Chiller 6\" at site \"MAIN\" were identified, but no historical data was found for the specified period. The known failure modes for the chiller were retrieved, but the process failed to proceed further due to serialization and validation errors." + }, + { + "id": 118, + "type": "FMSR", + "deterministic": false, + "question": "Purge unit of chiller 6 have possibility to excess purge, what is the plan by the maintenance experts to early detect the failure?", + "success": true, + "wall_time_seconds": 53.878557, + "phases": { + "discover": { + "count": 1, + "total_seconds": 1.842515, + "average_seconds": 1.842515 + }, + "execute": { + "count": 1, + "total_seconds": 40.924829, + "average_seconds": 40.924829 + }, + "plan": { + "count": 1, + "total_seconds": 9.173519, + "average_seconds": 9.173519 + }, + "summarise": { + "count": 1, + "total_seconds": 1.936245, + "average_seconds": 1.936245 + } + }, + "hardware": { + "sampler": "resource", + "sample_count": 30, + "cpu_percent_average": 3.931525, + "cpu_percent_peak": 94.95433, + "memory_rss_bytes_average": 235470848, + "memory_rss_bytes_peak": 235470848, + "process_cpu_time_seconds": 0.208681, + "child_cpu_time_seconds": 5.856775, + "child_max_rss_bytes": 241385472 + }, + "plan_steps": 9, + "tool_calls": 9, + "answer": "The task to determine a plan by maintenance experts to early detect the failure of \"Purge unit excess purge\" in chiller 6 was partially executed. The known failure modes for chiller 6 were identified, and \"Purge Unit Excessive purge\" was listed among them. However, due to errors in retrieving sensor data and executing subsequent analysis steps, a detailed plan for early detection could not be formulated. To develop a plan, the maintenance experts would need to successfully identify relevant sensors for chiller 6, analyze historical data, and perform time-series forecasting and anomaly detection. With the information available, the maintenance experts can focus on ensuring that the necessary sensor data for chiller 6 is available and correctly linked to the asset to enable further analysis and development of a predictive maintenance plan for the \"Purge Unit Excessive purge\" failure mode." + }, + { + "id": 119, + "type": "FMSR", + "deterministic": false, + "question": "Generate a machine learning recipe for detecting overheating failure for Chiller 6. Result should include feature sensors and target sensor.", + "success": true, + "wall_time_seconds": 29.700063, + "phases": { + "discover": { + "count": 1, + "total_seconds": 1.818416, + "average_seconds": 1.818416 + }, + "execute": { + "count": 1, + "total_seconds": 17.5715, + "average_seconds": 17.5715 + }, + "plan": { + "count": 1, + "total_seconds": 8.012595, + "average_seconds": 8.012595 + }, + "summarise": { + "count": 1, + "total_seconds": 2.29626, + "average_seconds": 2.29626 + } + }, + "hardware": { + "sampler": "resource", + "sample_count": 43, + "cpu_percent_average": 2.951795, + "cpu_percent_peak": 95.54195, + "memory_rss_bytes_average": 235470848, + "memory_rss_bytes_peak": 235470848, + "process_cpu_time_seconds": 0.171751, + "child_cpu_time_seconds": 5.299897, + "child_max_rss_bytes": 241385472 + }, + "plan_steps": 9, + "tool_calls": 6, + "answer": "To detect overheating failure for Chiller 6, the machine learning recipe involves the following:\n\n**Target Sensor:** Not explicitly identified due to execution errors, but based on the context, it is likely related to temperature or overheating indicators.\n\n**Feature Sensors:** \n1. Chiller 6 Liquid Refrigerant Evaporator Temperature\n2. Chiller 6 Return Temperature\n3. Chiller 6 Supply Temperature\n4. Chiller 6 Condenser Water Return To Tower Temperature\n5. Chiller 6 Power Input\n\nThese sensors are related to temperature measurements and power input, which are relevant for detecting overheating conditions. However, the exact feature and target sensors should be confirmed by re-executing the failed steps (Step 6 and Step 8) to ensure accuracy. \n\nThe dataset for training the model should be prepared using historical data from these sensors, spanning from \"2022-01-01\" to the current date." + }, + { + "id": 120, + "type": "FMSR", + "deterministic": false, + "question": "List all failure modes of Chiller 6 that can be detected by temperature sensors and power input sensors.", + "success": true, + "wall_time_seconds": 23.965006, + "phases": { + "discover": { + "count": 1, + "total_seconds": 1.890051, + "average_seconds": 1.890051 + }, + "execute": { + "count": 1, + "total_seconds": 14.181614, + "average_seconds": 14.181614 + }, + "plan": { + "count": 1, + "total_seconds": 5.011403, + "average_seconds": 5.011403 + }, + "summarise": { + "count": 1, + "total_seconds": 2.880694, + "average_seconds": 2.880694 + } + }, + "hardware": { + "sampler": "resource", + "sample_count": 39, + "cpu_percent_average": 3.036794, + "cpu_percent_peak": 93.22716, + "memory_rss_bytes_average": 235470848, + "memory_rss_bytes_peak": 235470848, + "process_cpu_time_seconds": 0.139511, + "child_cpu_time_seconds": 4.840223, + "child_max_rss_bytes": 241385472 + }, + "plan_steps": 7, + "tool_calls": 5, + "answer": "The list of failure modes of Chiller 6 that can be detected by temperature sensors and power input sensors is empty due to an error in determining the mapping between failure modes and sensors. However, based on the available data, the relevant sensors for Chiller 6 include temperature sensors (\"Chiller 6 Liquid Refrigerant Evaporator Temperature\", \"Chiller 6 Return Temperature\", \"Chiller 6 Supply Temperature\", \"Chiller 6 Condenser Water Return To Tower Temperature\", \"Chiller 6 Setpoint Temperature\") and a power input sensor (\"Chiller 6 Power Input\"). \n\nAlthough the exact mapping was not successfully retrieved, the failure modes retrieved include \"Compressor Overheating: Failed due to Normal wear, overheating\", \"Heat Exchangers: Fans: Degraded motor or worn bearing due to Normal use\", \"Evaporator Water side fouling\", \"Condenser Water side fouling\", \"Condenser Improper water side flow rate\", \"Purge Unit Excessive purge\", and \"Refrigerant Operated Control Valve Failed spring\". Some of these failure modes could potentially be related to the available temperature and power input sensors, but without the correct mapping, we cannot confirm the detectable failure modes.\n\nTherefore, the answer to the original question is: No detectable failure modes were returned." + }, + { + "id": 121, + "type": "FMSR", + "deterministic": false, + "question": "When compressor motor of a chiller fails, what is the temporal behavior of the power input.", + "success": true, + "wall_time_seconds": 35.45686, + "phases": { + "discover": { + "count": 1, + "total_seconds": 2.008973, + "average_seconds": 2.008973 + }, + "execute": { + "count": 1, + "total_seconds": 23.239302, + "average_seconds": 23.239302 + }, + "plan": { + "count": 1, + "total_seconds": 8.387456, + "average_seconds": 8.387456 + }, + "summarise": { + "count": 1, + "total_seconds": 1.819803, + "average_seconds": 1.819803 + } + }, + "hardware": { + "sampler": "resource", + "sample_count": 29, + "cpu_percent_average": 4.251431, + "cpu_percent_peak": 92.275677, + "memory_rss_bytes_average": 235470848, + "memory_rss_bytes_peak": 235470848, + "process_cpu_time_seconds": 0.186519, + "child_cpu_time_seconds": 5.587344, + "child_max_rss_bytes": 241385472 + }, + "plan_steps": 10, + "tool_calls": 8, + "answer": "The task to determine the temporal behavior of the power input when the compressor motor of a chiller fails was not successfully completed due to errors in the execution of steps 7, 8, 9, and 10. Specifically, the errors were related to missing sensor mappings, lack of historical observations, and unavailability of certain dependencies. Therefore, based on the provided results, it is not possible to provide a definitive answer to the original question regarding the temporal behavior of the power input." + }, + { + "id": 122, + "type": "FMSR", + "deterministic": false, + "question": "When power input of Chiller 6 drops, what is the potential failure that causes it?", + "success": true, + "wall_time_seconds": 32.53312, + "phases": { + "discover": { + "count": 1, + "total_seconds": 2.174011, + "average_seconds": 2.174011 + }, + "execute": { + "count": 1, + "total_seconds": 19.760929, + "average_seconds": 19.760929 + }, + "plan": { + "count": 1, + "total_seconds": 9.473073, + "average_seconds": 9.473073 + }, + "summarise": { + "count": 1, + "total_seconds": 1.123757, + "average_seconds": 1.123757 + } + }, + "hardware": { + "sampler": "resource", + "sample_count": 45, + "cpu_percent_average": 2.664245, + "cpu_percent_peak": 88.816066, + "memory_rss_bytes_average": 235470848, + "memory_rss_bytes_peak": 235470848, + "process_cpu_time_seconds": 0.186741, + "child_cpu_time_seconds": 5.622214, + "child_max_rss_bytes": 241385472 + }, + "plan_steps": 7, + "tool_calls": 6, + "answer": "The potential failure that causes the power input of Chiller 6 to drop is cavitation due to low refrigerant pressure or high inlet water temperature." + } + ] +} \ No newline at end of file diff --git a/plot_timing_heatmap.py b/plot_timing_heatmap.py new file mode 100644 index 000000000..4da98d9c6 --- /dev/null +++ b/plot_timing_heatmap.py @@ -0,0 +1,313 @@ +from __future__ import annotations + +import argparse +import html +import json +from pathlib import Path +from typing import Any + + +DEFAULT_INPUT = "artifacts/timing/fmsr_utterance_plan_execute.json" +DEFAULT_OUTPUT = "artifacts/timing/fmsr_utterance_cached_heatmap.svg" + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="Create a one-column SVG heatmap from a timing JSON artifact." + ) + parser.add_argument( + "--input", + default=DEFAULT_INPUT, + help="Timing JSON produced by time_fmsr_utterance.py.", + ) + parser.add_argument( + "--output", + default=DEFAULT_OUTPUT, + help="SVG file to write.", + ) + parser.add_argument( + "--metric", + default="wall_time_seconds", + help="Scenario-level metric to plot.", + ) + parser.add_argument( + "--column-label", + default="Cached", + help="Label for the single heatmap column.", + ) + parser.add_argument( + "--title", + default="Wall time heatmap with caching (lower = faster)", + help="Chart title.", + ) + return parser.parse_args() + + +def main() -> None: + args = parse_args() + data = json.loads(Path(args.input).read_text()) + if _is_cache_comparison(data): + rows = _extract_cache_comparison_rows(data) + svg = render_multi_column_heatmap( + rows, + title="Mean wall time by cache mode (lower = faster)", + column_labels=["No cache", "Cache"], + metric_label="Mean wall time (s)", + ) + else: + rows = _extract_rows(data, args.metric) + svg = render_one_column_heatmap( + rows, + title=args.title, + column_label=args.column_label, + metric_label=_metric_label(args.metric), + ) + + output_path = Path(args.output) + output_path.parent.mkdir(parents=True, exist_ok=True) + output_path.write_text(svg) + print(f"Wrote {output_path}") + + +def _extract_rows(data: dict[str, Any], metric: str) -> list[tuple[int, float]]: + rows: list[tuple[int, float]] = [] + for scenario in data.get("scenarios", []): + if metric not in scenario: + continue + rows.append((int(scenario["id"]), float(scenario[metric]))) + if not rows: + raise ValueError(f"No scenario rows found for metric {metric!r}") + return sorted(rows) + + +def _is_cache_comparison(data: dict[str, Any]) -> bool: + return bool(data.get("scenarios")) and all( + "no_cache" in scenario and "cache" in scenario + for scenario in data.get("scenarios", []) + ) + + +def _extract_cache_comparison_rows( + data: dict[str, Any], +) -> list[tuple[int, list[float | None]]]: + rows: list[tuple[int, list[float | None]]] = [] + for scenario in data.get("scenarios", []): + rows.append( + ( + int(scenario["id"]), + [ + scenario["no_cache"].get("average_wall_time_seconds"), + scenario["cache"].get("average_wall_time_seconds"), + ], + ) + ) + if not rows: + raise ValueError("No cache comparison rows found") + return sorted(rows) + + +def render_one_column_heatmap( + rows: list[tuple[int, float]], + *, + title: str, + column_label: str, + metric_label: str, +) -> str: + return render_multi_column_heatmap( + [(scenario_id, [value]) for scenario_id, value in rows], + title=title, + column_labels=[column_label], + metric_label=metric_label, + ) + + +def render_multi_column_heatmap( + rows: list[tuple[int, list[float | None]]], + *, + title: str, + column_labels: list[str], + metric_label: str, +) -> str: + margin_left = 92 + margin_top = 72 + cell_width = 155 + cell_height = 34 + colorbar_gap = 46 + colorbar_width = 30 + colorbar_height = max(cell_height * len(rows), 160) + title_height = 32 + x_label_height = 54 + right_margin = 130 + bottom_margin = 56 + + heatmap_width = cell_width * len(column_labels) + heatmap_height = cell_height * len(rows) + width = margin_left + heatmap_width + colorbar_gap + colorbar_width + right_margin + height = margin_top + title_height + heatmap_height + x_label_height + bottom_margin + grid_top = margin_top + title_height + colorbar_left = margin_left + heatmap_width + colorbar_gap + + values = [ + value + for _, row_values in rows + for value in row_values + if value is not None + ] + min_value = min(values) + max_value = max(values) + + parts = [ + '', + f'', + "", + '', + f'{html.escape(title)}', + ] + + for column_index, column_label in enumerate(column_labels): + x = margin_left + column_index * cell_width + cell_width / 2 + parts.append( + f'{html.escape(column_label)}' + ) + + for row_index, (scenario_id, row_values) in enumerate(rows): + y = grid_top + row_index * cell_height + parts.append( + f'{scenario_id}' + ) + for column_index, value in enumerate(row_values): + x = margin_left + column_index * cell_width + if value is None: + fill = "#d9d9d9" + text = "n/a" + text_fill = "#111" + else: + fill = _color_for_value(value, min_value, max_value) + text = f"{value:.1f}s" + text_fill = "#111" if _relative_luminance(fill) > 0.48 else "#f8f8f8" + parts.extend( + [ + f'', + f'{text}', + ] + ) + + parts.extend( + [ + f'', + f'Scenario ID', + f'Cache mode', + ] + ) + + parts.extend( + _render_colorbar( + left=colorbar_left, + top=grid_top, + width=colorbar_width, + height=colorbar_height, + min_value=min_value, + max_value=max_value, + label=metric_label, + ) + ) + parts.append("") + return "\n".join(parts) + + +def _render_colorbar( + *, + left: int, + top: int, + width: int, + height: int, + min_value: float, + max_value: float, + label: str, +) -> list[str]: + parts: list[str] = [] + steps = 80 + for index in range(steps): + ratio = index / (steps - 1) + value = max_value - ratio * (max_value - min_value) + y = top + ratio * height + fill = _color_for_value(value, min_value, max_value) + parts.append( + f'' + ) + + tick_values = _tick_values(min_value, max_value) + for value in tick_values: + ratio = 0.0 if max_value == min_value else (max_value - value) / (max_value - min_value) + y = top + ratio * height + parts.extend( + [ + f'', + f'{value:.0f}', + ] + ) + + parts.extend( + [ + f'', + f'{html.escape(label)}', + ] + ) + return parts + + +def _color_for_value(value: float, min_value: float, max_value: float) -> str: + if max_value == min_value: + ratio = 0.0 + else: + ratio = (value - min_value) / (max_value - min_value) + ratio = max(0.0, min(1.0, ratio)) + + green = (0, 104, 55) + yellow = (255, 255, 191) + red = (165, 0, 38) + if ratio < 0.5: + return _interpolate_color(green, yellow, ratio * 2) + return _interpolate_color(yellow, red, (ratio - 0.5) * 2) + + +def _interpolate_color( + start: tuple[int, int, int], + end: tuple[int, int, int], + ratio: float, +) -> str: + red = round(start[0] + (end[0] - start[0]) * ratio) + green = round(start[1] + (end[1] - start[1]) * ratio) + blue = round(start[2] + (end[2] - start[2]) * ratio) + return f"#{red:02x}{green:02x}{blue:02x}" + + +def _relative_luminance(hex_color: str) -> float: + red = int(hex_color[1:3], 16) / 255 + green = int(hex_color[3:5], 16) / 255 + blue = int(hex_color[5:7], 16) / 255 + return 0.2126 * red + 0.7152 * green + 0.0722 * blue + + +def _tick_values(min_value: float, max_value: float) -> list[float]: + if max_value == min_value: + return [min_value] + return [min_value, (min_value + max_value) / 2, max_value] + + +def _metric_label(metric: str) -> str: + labels = { + "wall_time_seconds": "Wall time (s)", + } + return labels.get(metric, metric.replace("_", " ")) + + +if __name__ == "__main__": + main() diff --git a/src/cache/cache.py b/src/cache/cache.py new file mode 100644 index 000000000..7525d42ec --- /dev/null +++ b/src/cache/cache.py @@ -0,0 +1,80 @@ +from collections import OrderedDict +import json +import os +from pathlib import Path +from typing import Any + +class Cache: + def __init__(self, cache_file: str, capacity: int = 10): + self.cache_file = Path(cache_file) + self.cache = OrderedDict() + self.capacity = capacity + self._load_cache() + + def get(self, key): + if _cache_disabled(): + return None + if key not in self.cache: + return None + self.cache.move_to_end(key) + return self.cache[key] + + def add(self, key, value): + if _cache_disabled(): + return + self._set(key, value) + self._save_cache() + + def add_many(self, entries): + if _cache_disabled(): + return + for key, value in entries.items(): + self._set(key, value) + self._save_cache() + + def _set(self, key, value): + if key not in self.cache and len(self.cache) >= self.capacity: + self.cache.popitem(last=False) + self.cache[key] = _json_safe(value) + self.cache.move_to_end(key) + + def _load_cache(self): + if not self.cache_file.exists(): + self.cache_file.parent.mkdir(parents=True, exist_ok=True) + self.cache_file.write_text("{}") + try: + with open(self.cache_file, "r") as f: + data = json.load(f) + self.cache = OrderedDict(data if isinstance(data, dict) else {}) + except json.JSONDecodeError: + self.cache = OrderedDict() + self._save_cache() + + def _save_cache(self): + self.cache_file.parent.mkdir(parents=True, exist_ok=True) + tmp_file = self.cache_file.with_name( + f".{self.cache_file.name}.{os.getpid()}.tmp" + ) + with open(tmp_file, "w") as f: + json.dump(self.cache, f) + f.flush() + os.fsync(f.fileno()) + os.replace(tmp_file, self.cache_file) + + +def _json_safe(value: Any) -> Any: + if hasattr(value, "model_dump"): + return value.model_dump() + if isinstance(value, dict): + return {key: _json_safe(item) for key, item in value.items()} + if isinstance(value, list): + return [_json_safe(item) for item in value] + return value + + +def _cache_disabled() -> bool: + return os.environ.get("ASSETOPSBENCH_DISABLE_CACHE", "").lower() in { + "1", + "true", + "yes", + } diff --git a/src/servers/fmsr/cache.json b/src/servers/fmsr/cache.json new file mode 100644 index 000000000..71a2294e9 --- /dev/null +++ b/src/servers/fmsr/cache.json @@ -0,0 +1 @@ +{"Chiller 6_Condenser Improper water side flow rate_Chiller 6 Supply Temperature": {"asset_name": "Chiller 6", "failure_mode": "Condenser Improper water side flow rate", "sensor": "Chiller 6 Supply Temperature", "relevancy_answer": "Yes", "relevancy_reason": "The sensor Chiller 6 Supply Temperature can help monitor or detect the failure because an improper water side flow rate in the condenser can affect the chiller's ability to cool properly, leading to changes in the supply temperature.", "temporal_behavior": "When the failure occurs, the Chiller 6 Supply Temperature sensor will likely show an increase in temperature over time, as the chiller's cooling capacity is reduced due to the improper water flow rate, resulting in warmer water being supplied to the system."}, "Chiller 6_Purge Unit Excessive purge_Chiller 6 Supply Temperature": {"asset_name": "Chiller 6", "failure_mode": "Purge Unit Excessive purge", "sensor": "Chiller 6 Supply Temperature", "relevancy_answer": "Yes", "relevancy_reason": "The sensor Chiller 6 Supply Temperature can help monitor or detect the failure Purge Unit Excessive purge because an excessive purge can lead to a change in the supply temperature of the chiller, which the sensor can detect.", "temporal_behavior": "When the failure Purge Unit Excessive purge occurs, the sensor Chiller 6 Supply Temperature may exhibit a sudden increase or fluctuation in temperature reading, indicating that the chiller is not operating efficiently due to the excessive purge."}, "Chiller 6_Refrigerant Operated Control Valve Failed spring_Chiller 6 Supply Temperature": {"asset_name": "Chiller 6", "failure_mode": "Refrigerant Operated Control Valve Failed spring", "sensor": "Chiller 6 Supply Temperature", "relevancy_answer": "Yes", "relevancy_reason": "The sensor Chiller 6 Supply Temperature can help monitor or detect the failure of the Refrigerant Operated Control Valve Failed spring in Chiller 6 because a malfunctioning control valve can affect the temperature of the supply water, which the sensor is measuring.", "temporal_behavior": "When the failure occurs, the Chiller 6 Supply Temperature sensor may exhibit abnormal temperature readings, such as a sudden increase or decrease in temperature, or unstable temperature fluctuations, indicating a problem with the chiller's operation."}, "Chiller 6_Compressor Overheating: Failed due to Normal wear, overheating_Chiller 6 Tonnage": {"asset_name": "Chiller 6", "failure_mode": "Compressor Overheating: Failed due to Normal wear, overheating", "sensor": "Chiller 6 Tonnage", "relevancy_answer": "No", "relevancy_reason": "The sensor Chiller 6 Tonnage is not related to monitoring or detecting compressor overheating, as tonnage refers to the cooling capacity of the chiller, not its temperature or operational state.", "temporal_behavior": "Unknown"}, "Chiller 6_Heat Exchangers: Fans: Degraded motor or worn bearing due to Normal use_Chiller 6 Tonnage": {"asset_name": "Chiller 6", "failure_mode": "Heat Exchangers: Fans: Degraded motor or worn bearing due to Normal use", "sensor": "Chiller 6 Tonnage", "relevancy_answer": "No", "relevancy_reason": "the sensor Chiller 6 Tonnage is not related to the failure mode of Heat Exchangers: Fans: Degraded motor or worn bearing due to Normal use, as it monitors the cooling capacity of the chiller, not the condition of the fans or their motors and bearings.", "temporal_behavior": "Unknown"}, "Chiller 6_Evaporator Water side fouling_Chiller 6 Tonnage": {"asset_name": "Chiller 6", "failure_mode": "Evaporator Water side fouling", "sensor": "Chiller 6 Tonnage", "relevancy_answer": "Yes", "relevancy_reason": "The sensor Chiller 6 Tonnage can help monitor or detect the failure Evaporator Water side fouling because a decrease in tonnage typically indicates a reduction in the chiller's cooling capacity, which can be caused by fouling on the evaporator water side.", "temporal_behavior": "When the failure Evaporator Water side fouling occurs, the sensor Chiller 6 Tonnage will likely show a gradual decrease in tonnage over time as the fouling reduces the heat transfer efficiency of the evaporator, leading to a decrease in the chiller's overall cooling capacity."}, "Chiller 6_Condenser Water side fouling_Chiller 6 Tonnage": {"asset_name": "Chiller 6", "failure_mode": "Condenser Water side fouling", "sensor": "Chiller 6 Tonnage", "relevancy_answer": "Yes", "relevancy_reason": "The sensor Chiller 6 Tonnage can help monitor or detect the failure because Condenser Water side fouling would likely cause a decrease in the chiller's cooling capacity, which would be reflected in a decrease in the tonnage reading.", "temporal_behavior": "When the failure occurs, the sensor Chiller 6 Tonnage would likely show a gradual decrease in tonnage over time as the fouling worsens, potentially with increased variability or fluctuations in the reading as the chiller struggles to maintain its cooling output."}, "Chiller 6_Condenser Improper water side flow rate_Chiller 6 Tonnage": {"asset_name": "Chiller 6", "failure_mode": "Condenser Improper water side flow rate", "sensor": "Chiller 6 Tonnage", "relevancy_answer": "Yes", "relevancy_reason": "The sensor Chiller 6 Tonnage can help monitor or detect the failure for Chiller 6 because an improper water side flow rate in the condenser can lead to a decrease in the chiller's cooling capacity, which can be reflected in the tonnage reading.", "temporal_behavior": "When the failure occurs, the sensor Chiller 6 Tonnage will likely show a decrease in the tonnage value over time, indicating a reduction in the chiller's cooling capacity due to the improper water side flow rate."}, "Chiller 6_Purge Unit Excessive purge_Chiller 6 Tonnage": {"asset_name": "Chiller 6", "failure_mode": "Purge Unit Excessive purge", "sensor": "Chiller 6 Tonnage", "relevancy_answer": "No", "relevancy_reason": "The sensor Chiller 6 Tonnage is related to the cooling capacity of the chiller, whereas the failure Purge Unit Excessive purge is related to the purge unit's operation, which is a separate system, so it's unlikely that the tonnage sensor can detect this specific failure.", "temporal_behavior": "Unknown"}, "Chiller 6_Refrigerant Operated Control Valve Failed spring_Chiller 6 Tonnage": {"asset_name": "Chiller 6", "failure_mode": "Refrigerant Operated Control Valve Failed spring", "sensor": "Chiller 6 Tonnage", "relevancy_answer": "No", "relevancy_reason": "The sensor Chiller 6 Tonnage is not related to the failure of the Refrigerant Operated Control Valve, as it measures the cooling capacity of the chiller, not the valve's operation.", "temporal_behavior": "Unknown"}} \ No newline at end of file diff --git a/src/servers/fmsr/main.py b/src/servers/fmsr/main.py index c945f7a42..ab67bc8e7 100644 --- a/src/servers/fmsr/main.py +++ b/src/servers/fmsr/main.py @@ -25,6 +25,7 @@ from dotenv import load_dotenv from mcp.server.fastmcp import FastMCP from pydantic import BaseModel +from cache.cache import Cache load_dotenv() @@ -108,10 +109,12 @@ def _build_llm(): try: _llm = _build_llm() _llm_available = True + _cache = Cache(str(Path(__file__).with_name("cache.json"))) except Exception as _e: logger.warning("LLM unavailable (FMSR will use curated data only): %s", _e) _llm = None _llm_available = False + _cache = None # ── LLM call helpers with retry ─────────────────────────────────────────────── @@ -188,6 +191,12 @@ def get_failure_modes(asset_name: str) -> Union[FailureModesResult, ErrorResult] if not asset_key or asset_key == "none": return ErrorResult(error="asset_name is required") + if _cache and _cache.get(asset_key): + return FailureModesResult( + asset_name=asset_name, + failure_modes=_cache.get(asset_key), + ) + if asset_key in _ASSET_FAILURE_MODES: return FailureModesResult( asset_name=asset_name, @@ -199,6 +208,8 @@ def get_failure_modes(asset_name: str) -> Union[FailureModesResult, ErrorResult] try: result = _call_asset2fm(asset_name) + if _cache: + _cache.add(asset_key, result) return FailureModesResult(asset_name=asset_name, failure_modes=result) except Exception as exc: logger.error("_call_asset2fm failed: %s", exc) @@ -231,27 +242,37 @@ def get_failure_mode_sensor_mapping( full_relevancy: List[RelevancyEntry] = [] fm2sensor: Dict[str, List[str]] = {} sensor2fm: Dict[str, List[str]] = {} + pending_cache_entries: dict[str, RelevancyEntry] = {} try: for s in sensors: for fm in failure_modes: - gen = _call_relevancy(asset_name, fm, s) - entry = RelevancyEntry( - asset_name=asset_name, - failure_mode=fm, - sensor=s, - relevancy_answer=gen["answer"], - relevancy_reason=gen["reason"], - temporal_behavior=gen["temporal_behavior"], - ) + cache_key = f"{asset_name}_{fm}_{s}" + if _cache and _cache.get(cache_key): + entry = RelevancyEntry(**_cache.get(cache_key)) + else: + gen = _call_relevancy(asset_name, fm, s) + entry = RelevancyEntry( + asset_name=asset_name, + failure_mode=fm, + sensor=s, + relevancy_answer=gen["answer"], + relevancy_reason=gen["reason"], + temporal_behavior=gen["temporal_behavior"], + ) + if _cache: + pending_cache_entries[cache_key] = entry full_relevancy.append(entry) - if "yes" in gen["answer"].lower(): + if "yes" in entry.relevancy_answer.lower(): fm2sensor.setdefault(fm, []).append(s) sensor2fm.setdefault(s, []).append(fm) except Exception as exc: logger.error("_call_relevancy failed: %s", exc) return ErrorResult(error=str(exc)) + if _cache and pending_cache_entries: + _cache.add_many(pending_cache_entries) + return FailureModeSensorMappingResult( metadata=MappingMetadata( asset_name=asset_name, diff --git a/src/servers/iot/cache.json b/src/servers/iot/cache.json new file mode 100644 index 000000000..9bba969de --- /dev/null +++ b/src/servers/iot/cache.json @@ -0,0 +1 @@ +{"asset_list": ["Chiller 6"], "sensor_list_Chiller 6": ["Chiller 6 Chiller % Loaded", "Chiller 6 Chiller Efficiency", "Chiller 6 Condenser Water Flow", "Chiller 6 Condenser Water Return To Tower Temperature", "Chiller 6 Liquid Refrigerant Evaporator Temperature", "Chiller 6 Power Input", "Chiller 6 Return Temperature", "Chiller 6 Schedule", "Chiller 6 Setpoint Temperature", "Chiller 6 Supply Temperature", "Chiller 6 Tonnage"]} \ No newline at end of file diff --git a/src/servers/iot/main.py b/src/servers/iot/main.py index 038b7fc1a..b8a73fe56 100644 --- a/src/servers/iot/main.py +++ b/src/servers/iot/main.py @@ -1,12 +1,13 @@ -import os import logging +import os +from pathlib import Path from datetime import datetime from typing import Any, Dict, List, Optional, Union from mcp.server.fastmcp import FastMCP from pydantic import BaseModel import couchdb3 from dotenv import load_dotenv - +from cache.cache import Cache load_dotenv() # Setup logging — default WARNING so stderr stays quiet when used as MCP server; @@ -33,6 +34,8 @@ mcp = FastMCP("IoTAgent") +_CACHE_FILE = Path(__file__).with_name("cache.json") +_cache = Cache(str(_CACHE_FILE)) # Static site as per original requirement SITES = ["MAIN"] @@ -75,6 +78,9 @@ def get_asset_list() -> List[str]: if not db: return [] + if _cache and _cache.get("asset_list"): + return _cache.get("asset_list") + # Using a mango query to find unique asset_ids might be slow without an index, # but for this benchmark we'll query documents and unique them. # In a production environment, we'd use a CouchDB view. @@ -84,6 +90,8 @@ def get_asset_list() -> List[str]: {"asset_id": {"$exists": True}}, fields=["asset_id"], limit=100000 ) assets = {doc["asset_id"] for doc in res["docs"] if "asset_id" in doc} + if _cache: + _cache.add("asset_list", sorted(list(assets))) return sorted(list(assets)) except Exception as e: logger.error(f"Error fetching assets: {e}") @@ -95,6 +103,9 @@ def get_sensor_list(asset_id: str) -> List[str]: if not db: return [] + if _cache and _cache.get(f"sensor_list_{asset_id}"): + return _cache.get(f"sensor_list_{asset_id}") + try: # Get one document for the asset to inspect keys res = db.find({"asset_id": asset_id}, limit=1) @@ -105,6 +116,8 @@ def get_sensor_list(asset_id: str) -> List[str]: # Exclude metadata and standard fields exclude = {"_id", "_rev", "asset_id", "timestamp"} sensors = [key for key in doc.keys() if key not in exclude] + if _cache: + _cache.add(f"sensor_list_{asset_id}", sorted(sensors)) return sorted(sensors) except Exception as e: logger.error(f"Error fetching sensors for {asset_id}: {e}") diff --git a/src/workflow/__init__.py b/src/workflow/__init__.py index d3e2d7eae..65fc45802 100644 --- a/src/workflow/__init__.py +++ b/src/workflow/__init__.py @@ -2,6 +2,11 @@ from .runner import PlanExecuteRunner from .models import OrchestratorResult, Plan, PlanStep, StepResult +from .timing import ( + compare_fmsr_utterance_cache_timing, + time_fmsr_utterance_scenarios, + time_scenarios, +) __all__ = [ "PlanExecuteRunner", @@ -9,4 +14,7 @@ "Plan", "PlanStep", "StepResult", + "compare_fmsr_utterance_cache_timing", + "time_fmsr_utterance_scenarios", + "time_scenarios", ] diff --git a/src/workflow/executor.py b/src/workflow/executor.py index 604ebf6b4..ad20038e5 100644 --- a/src/workflow/executor.py +++ b/src/workflow/executor.py @@ -176,7 +176,6 @@ async def execute_step( resolved_args = step.tool_args response = await _call_tool(server_path, step.tool, resolved_args) - print(f"Response for step {step.step_number}: {response}") return StepResult( step_number=step.step_number, task=step.task, @@ -432,7 +431,6 @@ async def _call_tool(server_path: Path | str, tool_name: str, args: dict) -> str async with ClientSession(read, write) as session: await session.initialize() result = await session.call_tool(tool_name, args) - print(f"Result for tool {tool_name} with args {args}: {result}") return _extract_content(result.content) diff --git a/src/workflow/tests/test_timing.py b/src/workflow/tests/test_timing.py new file mode 100644 index 000000000..54700117f --- /dev/null +++ b/src/workflow/tests/test_timing.py @@ -0,0 +1,58 @@ +from __future__ import annotations + +import argparse +import asyncio +import json +from pathlib import Path + +from dotenv import load_dotenv +from llm.litellm import LiteLLMBackend +from workflow import time_fmsr_utterance_scenarios + + +DEFAULT_MODEL = "watsonx/meta-llama/llama-4-maverick-17b-128e-instruct-fp8" + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="Time all FMSR utterance scenarios with plan-execute." + ) + parser.add_argument("--model-id", default=DEFAULT_MODEL) + parser.add_argument( + "--output", + default="artifacts/timing/fmsr_utterance_plan_execute.json", + ) + parser.add_argument("--limit", type=int, default=None) + parser.add_argument("--scenario-id", type=int, action="append", default=None) + parser.add_argument("--sample-interval", type=float, default=0.25) + parser.add_argument("--exclude-answers", action="store_true") + return parser.parse_args() + + +async def main() -> None: + load_dotenv() + args = parse_args() + + llm = LiteLLMBackend(model_id=args.model_id) + + summary = await time_fmsr_utterance_scenarios( + llm=llm, + output_path=Path(args.output), + limit=args.limit, + scenario_ids=args.scenario_id, + hardware_sample_interval_seconds=args.sample_interval, + include_answers=not args.exclude_answers, + ) + + print(json.dumps({ + "scenario_count": summary["scenario_count"], + "successful": summary["successful"], + "failed": summary["failed"], + "total_wall_time_seconds": summary["total_wall_time_seconds"], + "hardware": summary["hardware"], + "output": args.output, + }, indent=2)) + + +if __name__ == "__main__": + asyncio.run(main()) \ No newline at end of file diff --git a/src/workflow/timing.py b/src/workflow/timing.py index edca59254..3bc911de3 100644 --- a/src/workflow/timing.py +++ b/src/workflow/timing.py @@ -25,7 +25,11 @@ from __future__ import annotations +import asyncio import json +import os +import resource +import sys import time from contextlib import contextmanager from dataclasses import dataclass, field @@ -33,6 +37,20 @@ from typing import Any +DEFAULT_FMSR_UTTERANCE_SCENARIOS = ( + Path(__file__).resolve().parents[1] + / "tmp" + / "meta_agent" + / "scenarios" + / "single_agent" + / "fmsr_utterance.json" +) +DEFAULT_CACHE_FILES = ( + Path(__file__).resolve().parents[1] / "servers" / "iot" / "cache.json", + Path(__file__).resolve().parents[1] / "servers" / "fmsr" / "cache.json", +) + + def _load_wandb(): try: import wandb @@ -184,3 +202,719 @@ def finish( self._wandb_run = None return summary + + +@dataclass +class HardwareMetrics: + """CPU and memory summary sampled during a measured block.""" + + sampler: str + sample_count: int + cpu_percent_average: float + cpu_percent_peak: float + memory_rss_bytes_average: int + memory_rss_bytes_peak: int + process_cpu_time_seconds: float + child_cpu_time_seconds: float + child_max_rss_bytes: int + + def to_dict(self) -> dict[str, Any]: + return { + "sampler": self.sampler, + "sample_count": self.sample_count, + "cpu_percent_average": self.cpu_percent_average, + "cpu_percent_peak": self.cpu_percent_peak, + "memory_rss_bytes_average": self.memory_rss_bytes_average, + "memory_rss_bytes_peak": self.memory_rss_bytes_peak, + "process_cpu_time_seconds": self.process_cpu_time_seconds, + "child_cpu_time_seconds": self.child_cpu_time_seconds, + "child_max_rss_bytes": self.child_max_rss_bytes, + } + + +class HardwareMonitor: + """Sample CPU percent and RSS for the current process while async work runs. + + If psutil is installed, child MCP server processes are included in live + samples. The stdlib fallback reports process CPU percent and max RSS. + """ + + def __init__(self, sample_interval_seconds: float = 0.25) -> None: + self.sample_interval_seconds = max(sample_interval_seconds, 0.01) + self._samples: list[tuple[float, int]] = [] + self._task: asyncio.Task | None = None + self._running = False + self._sampler = "resource" + self._psutil: Any | None = None + self._process: Any | None = None + self._start_process_time = 0.0 + self._start_children_usage: Any | None = None + self._last_wall = 0.0 + self._last_process_time = 0.0 + + async def __aenter__(self) -> "HardwareMonitor": + self.start() + return self + + async def __aexit__(self, exc_type, exc, tb) -> None: + await self.stop() + + def start(self) -> None: + self._psutil = _load_psutil() + if self._psutil is not None: + self._sampler = "psutil" + self._process = self._psutil.Process(os.getpid()) + self._prime_psutil_cpu_counters() + + self._start_process_time = time.process_time() + self._start_children_usage = resource.getrusage(resource.RUSAGE_CHILDREN) + self._last_wall = time.perf_counter() + self._last_process_time = self._start_process_time + self._running = True + self._task = asyncio.create_task(self._sample_loop()) + + async def stop(self) -> HardwareMetrics: + self._running = False + if self._task is not None: + await self._task + self._sample_once() + return self.metrics() + + def metrics(self) -> HardwareMetrics: + samples = self._samples + cpu_values = [sample[0] for sample in samples] + memory_values = [sample[1] for sample in samples] + child_usage = resource.getrusage(resource.RUSAGE_CHILDREN) + start_child_usage = self._start_children_usage or child_usage + child_cpu_seconds = ( + child_usage.ru_utime + + child_usage.ru_stime + - start_child_usage.ru_utime + - start_child_usage.ru_stime + ) + + return HardwareMetrics( + sampler=self._sampler, + sample_count=len(samples), + cpu_percent_average=round(_average(cpu_values), 6), + cpu_percent_peak=round(max(cpu_values, default=0.0), 6), + memory_rss_bytes_average=round(_average(memory_values)), + memory_rss_bytes_peak=max(memory_values, default=0), + process_cpu_time_seconds=round( + time.process_time() - self._start_process_time, 6 + ), + child_cpu_time_seconds=round(child_cpu_seconds, 6), + child_max_rss_bytes=_maxrss_to_bytes(child_usage.ru_maxrss), + ) + + async def _sample_loop(self) -> None: + while self._running: + self._sample_once() + await asyncio.sleep(self.sample_interval_seconds) + + def _sample_once(self) -> None: + if self._psutil is not None and self._process is not None: + try: + processes = [self._process] + self._process.children(recursive=True) + cpu_percent = 0.0 + rss_bytes = 0 + for process in processes: + with process.oneshot(): + cpu_percent += process.cpu_percent(interval=None) + rss_bytes += process.memory_info().rss + self._samples.append((cpu_percent, rss_bytes)) + return + except Exception: # noqa: BLE001 + self._sampler = "resource" + + now = time.perf_counter() + process_time = time.process_time() + wall_delta = max(now - self._last_wall, 1e-9) + cpu_delta = max(process_time - self._last_process_time, 0.0) + usage = resource.getrusage(resource.RUSAGE_SELF) + self._samples.append( + ((cpu_delta / wall_delta) * 100.0, _maxrss_to_bytes(usage.ru_maxrss)) + ) + self._last_wall = now + self._last_process_time = process_time + + def _prime_psutil_cpu_counters(self) -> None: + try: + processes = [self._process] + self._process.children(recursive=True) + for process in processes: + process.cpu_percent(interval=None) + except Exception: # noqa: BLE001 + self._sampler = "resource" + self._psutil = None + self._process = None + + +async def time_scenarios( + *, + llm: Any | None = None, + runner: Any | None = None, + scenario_path: str | Path = DEFAULT_FMSR_UTTERANCE_SCENARIOS, + output_path: str | Path | None = None, + limit: int | None = None, + scenario_ids: list[int] | set[int] | None = None, + server_paths: dict[str, Path | str] | None = None, + hardware_sample_interval_seconds: float = 0.25, + include_answers: bool = True, + continue_on_error: bool = True, + show_progress: bool = False, +) -> dict[str, Any]: + """Run plan-execute over scenario utterances and collect timing metrics. + + Args: + llm: LLM backend used to construct a PlanExecuteRunner when ``runner`` + is not supplied. + runner: Optional pre-built runner with ``await run(question, timer=...)``. + scenario_path: JSON list of scenarios containing at least ``id`` and + ``text`` fields. + output_path: Optional JSON file path for the summary. + limit: Optional maximum number of filtered scenarios to run. + scenario_ids: Optional set/list of integer scenario ids to include. + server_paths: Optional MCP server overrides when building the runner. + hardware_sample_interval_seconds: CPU/RSS sampling interval. + include_answers: Include final answers in the summary JSON. + continue_on_error: Record failed scenarios and continue when true. + show_progress: Show a tqdm progress bar while scenarios run. + + Returns: + A serializable dict with per-scenario wall time, runner phase timings, + sampled CPU percent, and memory RSS metrics. + """ + + scenarios = _load_scenarios(scenario_path, scenario_ids=scenario_ids, limit=limit) + if runner is None: + if llm is None: + raise ValueError("time_scenarios requires either llm or runner") + from .runner import PlanExecuteRunner + + runner = PlanExecuteRunner(llm=llm, server_paths=server_paths) + + batch_started_at = time.perf_counter() + scenario_results: list[dict[str, Any]] = [] + + progress = _make_progress_bar(scenarios, enabled=show_progress) + try: + async with HardwareMonitor(hardware_sample_interval_seconds) as batch_monitor: + for scenario in progress: + scenario_result = await _time_one_scenario( + runner=runner, + scenario=scenario, + hardware_sample_interval_seconds=hardware_sample_interval_seconds, + include_answer=include_answers, + continue_on_error=continue_on_error, + ) + scenario_results.append(scenario_result) + _update_progress_postfix(progress, scenario_result) + finally: + if hasattr(progress, "close"): + progress.close() + + successful = sum(1 for result in scenario_results if result["success"]) + summary = { + "scenario_path": str(Path(scenario_path)), + "scenario_count": len(scenario_results), + "successful": successful, + "failed": len(scenario_results) - successful, + "total_wall_time_seconds": round(time.perf_counter() - batch_started_at, 6), + "hardware": batch_monitor.metrics().to_dict(), + "scenarios": scenario_results, + } + + if output_path is not None: + path = Path(output_path) + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(json.dumps(summary, indent=2)) + + return summary + + +async def time_fmsr_utterance_scenarios( + *, + llm: Any | None = None, + runner: Any | None = None, + output_path: str | Path | None = None, + limit: int | None = None, + scenario_ids: list[int] | set[int] | None = None, + server_paths: dict[str, Path | str] | None = None, + hardware_sample_interval_seconds: float = 0.25, + include_answers: bool = True, + continue_on_error: bool = True, + show_progress: bool = False, +) -> dict[str, Any]: + """Convenience wrapper for ``src/tmp/.../fmsr_utterance.json``.""" + + return await time_scenarios( + llm=llm, + runner=runner, + scenario_path=DEFAULT_FMSR_UTTERANCE_SCENARIOS, + output_path=output_path, + limit=limit, + scenario_ids=scenario_ids, + server_paths=server_paths, + hardware_sample_interval_seconds=hardware_sample_interval_seconds, + include_answers=include_answers, + continue_on_error=continue_on_error, + show_progress=show_progress, + ) + + +async def compare_fmsr_utterance_cache_timing( + *, + llm: Any | None = None, + runner: Any | None = None, + output_path: str | Path | None = ( + "artifacts/timing/fmsr_utterance_cache_comparison.json" + ), + limit: int | None = None, + scenario_ids: list[int] | set[int] | None = None, + server_paths: dict[str, Path | str] | None = None, + repeats: int = 3, + hardware_sample_interval_seconds: float = 0.25, + include_answers: bool = False, + continue_on_error: bool = True, + show_progress: bool = False, + cache_files: tuple[Path, ...] = DEFAULT_CACHE_FILES, + restore_cache_after: bool = True, + resume: bool = True, +) -> dict[str, Any]: + """Compare plan-execute timings with cache disabled vs enabled. + + For each scenario this runs ``repeats`` no-cache trials with cache reads and + writes disabled, then clears cache files and runs ``repeats`` cached trials. + Cached trials share cache state, so the first cached run can populate cache + and later cached runs can benefit from it. + """ + + scenarios = _load_scenarios( + DEFAULT_FMSR_UTTERANCE_SCENARIOS, + scenario_ids=scenario_ids, + limit=limit, + ) + if runner is None: + if llm is None: + raise ValueError( + "compare_fmsr_utterance_cache_timing requires either llm or runner" + ) + from .runner import PlanExecuteRunner + + runner = PlanExecuteRunner(llm=llm, server_paths=server_paths) + + batch_started_at = time.perf_counter() + output_file = Path(output_path) if output_path is not None else None + completed_by_id = ( + _load_completed_comparison(output_file, repeats) + if resume and output_file is not None + else {} + ) + scenario_results: list[dict[str, Any]] = [] + cache_snapshots = ( + _snapshot_cache_files(cache_files) if restore_cache_after else None + ) + progress_items = [ + (scenario, mode, run_index) + for scenario in scenarios + if scenario.get("id") not in completed_by_id + for mode in ("no_cache", "cache") + for run_index in range(1, repeats + 1) + ] + progress = _make_progress_bar( + progress_items, + enabled=show_progress, + desc="Comparing cache timing", + unit="run", + ) + + try: + for scenario in scenarios: + if scenario.get("id") in completed_by_id: + scenario_results.append(completed_by_id[scenario.get("id")]) + continue + + _clear_cache_files(cache_files) + no_cache_runs = [] + with _cache_mode(disabled=True): + for run_index in range(1, repeats + 1): + result = await _time_one_scenario( + runner=runner, + scenario=scenario, + hardware_sample_interval_seconds=( + hardware_sample_interval_seconds + ), + include_answer=include_answers, + continue_on_error=continue_on_error, + ) + result["run_index"] = run_index + no_cache_runs.append(result) + _advance_progress(progress, result, "no_cache", run_index) + + _clear_cache_files(cache_files) + cache_runs = [] + with _cache_mode(disabled=False): + for run_index in range(1, repeats + 1): + result = await _time_one_scenario( + runner=runner, + scenario=scenario, + hardware_sample_interval_seconds=( + hardware_sample_interval_seconds + ), + include_answer=include_answers, + continue_on_error=continue_on_error, + ) + result["run_index"] = run_index + cache_runs.append(result) + _advance_progress(progress, result, "cache", run_index) + + scenario_results.append( + _build_cache_comparison_scenario_result( + scenario=scenario, + no_cache_runs=no_cache_runs, + cache_runs=cache_runs, + ) + ) + if output_file is not None: + _write_json_atomic( + output_file, + _build_cache_comparison_summary( + scenario_results=scenario_results, + repeats=repeats, + batch_started_at=batch_started_at, + cache_files=cache_files, + restore_cache_after=restore_cache_after, + resume=resume, + complete=False, + ), + ) + finally: + if hasattr(progress, "close"): + progress.close() + if cache_snapshots is not None: + _restore_cache_files(cache_snapshots) + + summary = _build_cache_comparison_summary( + scenario_results=scenario_results, + repeats=repeats, + batch_started_at=batch_started_at, + cache_files=cache_files, + restore_cache_after=restore_cache_after, + resume=resume, + complete=True, + ) + + if output_file is not None: + _write_json_atomic(output_file, summary) + + return summary + + +def _build_cache_comparison_scenario_result( + *, + scenario: dict[str, Any], + no_cache_runs: list[dict[str, Any]], + cache_runs: list[dict[str, Any]], +) -> dict[str, Any]: + no_cache_avg = _average_successful_wall_time(no_cache_runs) + cache_avg = _average_successful_wall_time(cache_runs) + return { + "id": scenario.get("id"), + "type": scenario.get("type"), + "deterministic": scenario.get("deterministic"), + "question": scenario["text"], + "no_cache": { + "average_wall_time_seconds": no_cache_avg, + "runs": no_cache_runs, + }, + "cache": { + "average_wall_time_seconds": cache_avg, + "runs": cache_runs, + }, + "improvement_seconds": ( + round(no_cache_avg - cache_avg, 6) + if no_cache_avg is not None and cache_avg is not None + else None + ), + "improvement_percent": ( + round(((no_cache_avg - cache_avg) / no_cache_avg) * 100, 6) + if no_cache_avg and cache_avg is not None + else None + ), + } + + +def _build_cache_comparison_summary( + *, + scenario_results: list[dict[str, Any]], + repeats: int, + batch_started_at: float, + cache_files: tuple[Path, ...], + restore_cache_after: bool, + resume: bool, + complete: bool, +) -> dict[str, Any]: + return { + "scenario_path": str(DEFAULT_FMSR_UTTERANCE_SCENARIOS), + "scenario_count": len(scenario_results), + "repeats_per_mode": repeats, + "modes": ["no_cache", "cache"], + "total_wall_time_seconds": round(time.perf_counter() - batch_started_at, 6), + "cache_files": [str(path) for path in cache_files], + "restore_cache_after": restore_cache_after, + "checkpoint": { + "resumable": True, + "resume_enabled": resume, + "complete": complete, + "completed_scenarios": len(scenario_results), + }, + "scenarios": scenario_results, + } + + +def _load_completed_comparison( + output_path: Path | None, + repeats: int, +) -> dict[int, dict[str, Any]]: + if output_path is None or not output_path.exists(): + return {} + try: + data = json.loads(output_path.read_text()) + except json.JSONDecodeError: + return {} + + completed: dict[int, dict[str, Any]] = {} + for scenario in data.get("scenarios", []): + scenario_id = scenario.get("id") + if scenario_id is None: + continue + no_cache_runs = scenario.get("no_cache", {}).get("runs", []) + cache_runs = scenario.get("cache", {}).get("runs", []) + if len(no_cache_runs) >= repeats and len(cache_runs) >= repeats: + completed[int(scenario_id)] = scenario + return completed + + +async def _time_one_scenario( + *, + runner: Any, + scenario: dict[str, Any], + hardware_sample_interval_seconds: float, + include_answer: bool, + continue_on_error: bool, +) -> dict[str, Any]: + scenario_id = scenario.get("id") + question = scenario["text"] + timer = TimingRun( + run_name=f"plan_execute_fmsr_utterance_{scenario_id}", + group="fmsr_utterance", + config={ + "scenario_id": scenario_id, + "scenario_type": scenario.get("type"), + "orchestrator": "plan_execute", + }, + ) + + started_at = time.perf_counter() + try: + async with HardwareMonitor(hardware_sample_interval_seconds) as monitor: + result = await runner.run(question, timer=timer) + timing_summary = timer.finish( + extra_metrics={ + "scenario_id": scenario_id, + "plan_steps": len(result.plan.steps), + "tool_calls": _count_tool_calls(result), + } + ) + scenario_result: dict[str, Any] = { + "id": scenario_id, + "type": scenario.get("type"), + "deterministic": scenario.get("deterministic"), + "question": question, + "success": all(step.success for step in result.history), + "wall_time_seconds": round(time.perf_counter() - started_at, 6), + "phases": timing_summary.phases, + "hardware": monitor.metrics().to_dict(), + "plan_steps": len(result.plan.steps), + "tool_calls": _count_tool_calls(result), + } + if include_answer: + scenario_result["answer"] = result.answer + return scenario_result + except Exception as exc: # noqa: BLE001 + if not continue_on_error: + raise + timing_summary = timer.finish(extra_metrics={"scenario_id": scenario_id}) + return { + "id": scenario_id, + "type": scenario.get("type"), + "deterministic": scenario.get("deterministic"), + "question": question, + "success": False, + "wall_time_seconds": round(time.perf_counter() - started_at, 6), + "phases": timing_summary.phases, + "hardware": monitor.metrics().to_dict() if "monitor" in locals() else {}, + "error": str(exc), + } + + +def _load_scenarios( + scenario_path: str | Path, + *, + scenario_ids: list[int] | set[int] | None = None, + limit: int | None = None, +) -> list[dict[str, Any]]: + scenarios = json.loads(Path(scenario_path).read_text()) + if not isinstance(scenarios, list): + raise ValueError(f"Expected a JSON list in {scenario_path}") + + selected_ids = set(scenario_ids or []) + filtered = [ + scenario + for scenario in scenarios + if isinstance(scenario, dict) + and "text" in scenario + and (not selected_ids or scenario.get("id") in selected_ids) + ] + if limit is not None: + filtered = filtered[:limit] + return filtered + + +def _count_tool_calls(result: Any) -> int: + return sum( + 1 + for step in result.history + if step.tool and step.tool.lower() not in ("none", "null") + ) + + +def _make_progress_bar( + scenarios: list[Any], + *, + enabled: bool, + desc: str = "Timing FMSR scenarios", + unit: str = "scenario", +) -> Any: + if not enabled: + return scenarios + try: + from tqdm.auto import tqdm + except ImportError: + return scenarios + return tqdm( + scenarios, + total=len(scenarios), + desc=desc, + unit=unit, + ) + + +def _update_progress_postfix(progress: Any, scenario_result: dict[str, Any]) -> None: + if not hasattr(progress, "set_postfix"): + return + progress.set_postfix( + id=scenario_result.get("id"), + ok=scenario_result.get("success"), + wall=f"{scenario_result.get('wall_time_seconds', 0.0):.2f}s", + ) + + +def _advance_progress( + progress: Any, + scenario_result: dict[str, Any], + mode: str, + run_index: int, +) -> None: + _update_progress_postfix(progress, scenario_result | {"mode": mode}) + if hasattr(progress, "set_postfix"): + progress.set_postfix( + mode=mode, + run=run_index, + id=scenario_result.get("id"), + ok=scenario_result.get("success"), + wall=f"{scenario_result.get('wall_time_seconds', 0.0):.2f}s", + ) + if hasattr(progress, "update"): + progress.update(1) + + +@contextmanager +def _cache_mode(*, disabled: bool): + previous = os.environ.get("ASSETOPSBENCH_DISABLE_CACHE") + if disabled: + os.environ["ASSETOPSBENCH_DISABLE_CACHE"] = "1" + else: + os.environ.pop("ASSETOPSBENCH_DISABLE_CACHE", None) + try: + yield + finally: + if previous is None: + os.environ.pop("ASSETOPSBENCH_DISABLE_CACHE", None) + else: + os.environ["ASSETOPSBENCH_DISABLE_CACHE"] = previous + + +def _clear_cache_files(cache_files: tuple[Path, ...]) -> None: + for cache_file in cache_files: + cache_file.parent.mkdir(parents=True, exist_ok=True) + _write_json_atomic(cache_file, {}) + + +def _snapshot_cache_files(cache_files: tuple[Path, ...]) -> dict[Path, str | None]: + return { + cache_file: cache_file.read_text() if cache_file.exists() else None + for cache_file in cache_files + } + + +def _restore_cache_files(snapshots: dict[Path, str | None]) -> None: + for cache_file, contents in snapshots.items(): + if contents is None: + if cache_file.exists(): + cache_file.unlink() + continue + cache_file.parent.mkdir(parents=True, exist_ok=True) + tmp_file = cache_file.with_name(f".{cache_file.name}.{os.getpid()}.tmp") + tmp_file.write_text(contents) + os.replace(tmp_file, cache_file) + + +def _write_json_atomic(path: Path, payload: dict[str, Any]) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + tmp_file = path.with_name(f".{path.name}.{os.getpid()}.tmp") + with open(tmp_file, "w") as f: + json.dump(payload, f) + f.flush() + os.fsync(f.fileno()) + os.replace(tmp_file, path) + + +def _average_successful_wall_time(runs: list[dict[str, Any]]) -> float | None: + values = [ + run["wall_time_seconds"] + for run in runs + if run.get("success") and "wall_time_seconds" in run + ] + if not values: + return None + return round(_average(values), 6) + + +def _load_psutil() -> Any | None: + try: + import psutil + + return psutil + except ImportError: + return None + + +def _average(values: list[float] | list[int]) -> float: + return sum(values) / len(values) if values else 0.0 + + +def _maxrss_to_bytes(value: int) -> int: + if sys.platform == "darwin": + return value + return value * 1024 diff --git a/time_fmsr_utterance.py b/time_fmsr_utterance.py new file mode 100644 index 000000000..5ea02baaf --- /dev/null +++ b/time_fmsr_utterance.py @@ -0,0 +1,197 @@ +from __future__ import annotations + +import argparse +import asyncio +import json +from pathlib import Path + +from dotenv import load_dotenv +from llm.litellm import LiteLLMBackend +from workflow import ( + compare_fmsr_utterance_cache_timing, + time_fmsr_utterance_scenarios, +) + + +DEFAULT_MODEL = "watsonx/meta-llama/llama-4-maverick-17b-128e-instruct-fp8" +DEFAULT_TIMING_OUTPUT = "artifacts/timing/fmsr_utterance_plan_execute.json" +DEFAULT_COMPARISON_OUTPUT = "artifacts/timing/fmsr_utterance_cache_comparison.json" +DEFAULT_COMPARISON_HEATMAP = "artifacts/timing/fmsr_utterance_cache_comparison.svg" + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="Time FMSR utterance scenarios with workflow plan-execute." + ) + parser.add_argument("--model-id", default=DEFAULT_MODEL) + parser.add_argument( + "--output", + default=None, + help="Path to write the full JSON timing summary.", + ) + parser.add_argument( + "--compare-cache", + action="store_true", + help="Run each scenario with cache disabled and enabled, then compare averages.", + ) + parser.add_argument( + "--repeats", + type=int, + default=3, + help="Number of runs per scenario per cache mode when --compare-cache is used.", + ) + parser.add_argument( + "--heatmap-output", + default=DEFAULT_COMPARISON_HEATMAP, + help="SVG heatmap path for --compare-cache.", + ) + parser.add_argument( + "--leave-cache-state", + action="store_true", + help="Do not restore cache files after --compare-cache finishes.", + ) + parser.add_argument( + "--no-resume", + action="store_true", + help="Do not resume from an existing --compare-cache output JSON.", + ) + parser.add_argument( + "--reset-checkpoint", + action="store_true", + help="Delete an existing --compare-cache output JSON before running.", + ) + parser.add_argument( + "--limit", + type=int, + default=None, + help="Optional number of scenarios to run for a smoke test.", + ) + parser.add_argument( + "--scenario-id", + type=int, + action="append", + default=None, + help="Run only the selected scenario id. Repeatable.", + ) + parser.add_argument( + "--sample-interval", + type=float, + default=0.25, + help="Hardware metrics sampling interval in seconds.", + ) + parser.add_argument( + "--exclude-answers", + action="store_true", + help="Do not include final LLM answers in the output JSON.", + ) + parser.add_argument( + "--stop-on-error", + action="store_true", + help="Stop immediately instead of recording failed scenarios and continuing.", + ) + parser.add_argument( + "--no-progress", + action="store_true", + default=False, + help="Disable the tqdm scenario progress bar.", + ) + return parser.parse_args() + + +async def main() -> None: + load_dotenv() + args = parse_args() + + llm = LiteLLMBackend(model_id=args.model_id) + output = args.output or ( + DEFAULT_COMPARISON_OUTPUT if args.compare_cache else DEFAULT_TIMING_OUTPUT + ) + + if args.compare_cache: + if args.reset_checkpoint: + Path(output).unlink(missing_ok=True) + summary = await compare_fmsr_utterance_cache_timing( + llm=llm, + output_path=Path(output), + limit=args.limit, + scenario_ids=args.scenario_id, + repeats=args.repeats, + hardware_sample_interval_seconds=args.sample_interval, + include_answers=not args.exclude_answers, + continue_on_error=not args.stop_on_error, + show_progress=not args.no_progress, + restore_cache_after=not args.leave_cache_state, + resume=not args.no_resume, + ) + _write_cache_comparison_heatmap(summary, Path(args.heatmap_output)) + print( + json.dumps( + { + "scenario_count": summary["scenario_count"], + "repeats_per_mode": summary["repeats_per_mode"], + "total_wall_time_seconds": summary["total_wall_time_seconds"], + "output": output, + "heatmap_output": args.heatmap_output, + }, + indent=2, + ) + ) + return + + summary = await time_fmsr_utterance_scenarios( + llm=llm, + output_path=Path(output), + limit=args.limit, + scenario_ids=args.scenario_id, + hardware_sample_interval_seconds=args.sample_interval, + include_answers=not args.exclude_answers, + continue_on_error=not args.stop_on_error, + show_progress=not args.no_progress, + ) + + failed_ids = [ + scenario["id"] + for scenario in summary["scenarios"] + if not scenario["success"] + ] + print( + json.dumps( + { + "scenario_count": summary["scenario_count"], + "successful": summary["successful"], + "failed": summary["failed"], + "failed_ids": failed_ids, + "total_wall_time_seconds": summary["total_wall_time_seconds"], + "hardware": summary["hardware"], + "output": output, + }, + indent=2, + ) + ) + + +def _write_cache_comparison_heatmap(summary: dict, output_path: Path) -> None: + from plot_timing_heatmap import render_multi_column_heatmap + + rows = [ + ( + int(scenario["id"]), + [ + scenario["no_cache"].get("average_wall_time_seconds"), + scenario["cache"].get("average_wall_time_seconds"), + ], + ) + for scenario in summary["scenarios"] + ] + svg = render_multi_column_heatmap( + rows, + title="Mean wall time by cache mode (lower = faster)", + column_labels=["No cache", "Cache"], + metric_label="Mean wall time (s)", + ) + output_path.parent.mkdir(parents=True, exist_ok=True) + output_path.write_text(svg) + + +if __name__ == "__main__": + asyncio.run(main())