From a32757abe35a37ed32fcf93ac2bd4dbd6be7f739 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Emil=20W=C3=A5reus?=
Date: Thu, 5 Feb 2026 13:10:26 +0100
Subject: [PATCH 1/2] feat: Implement Deep Research presentation layout and
slides
- Added a new layout component for the Deep Research presentation, enabling navigation through slides with keyboard controls.
- Created individual slide components for each topic, including title, group project, results, and various insights related to AI research.
- Implemented a progress bar and slide counter for enhanced user experience during presentations.
- Introduced dynamic metadata generation for slides based on their content, improving SEO and accessibility.
- Ensured smooth transitions between slides using framer-motion for a polished presentation experience.
---
.gitignore | 3 +-
.../deep-research/[slide]/page.tsx | 132 ++
app/presentations/deep-research/layout.tsx | 106 +
app/presentations/deep-research/page.tsx | 7 +
app/status/page.tsx | 6 +-
.../diffusion/diffusion-overview.tsx | 8 +-
.../animations/diffusion/draft-denoising.tsx | 41 +-
.../animations/diffusion/parallel-agents.tsx | 18 +-
.../deep-research/slides/01-title.tsx | 36 +
.../deep-research/slides/02-group-project.tsx | 54 +
.../deep-research/slides/03-the-result.tsx | 34 +
.../deep-research/slides/04-the-reveal.tsx | 60 +
.../deep-research/slides/05-about.tsx | 180 ++
.../deep-research/slides/06-audience-poll.tsx | 38 +
.../deep-research/slides/07-timeline.tsx | 73 +
.../deep-research/slides/08-cot.tsx | 66 +
.../deep-research/slides/08-storm-intro.tsx | 69 +
.../deep-research/slides/09-react-demo.tsx | 46 +
.../deep-research/slides/09-react.tsx | 89 +
.../slides/09-storm-architecture.tsx | 244 +++
.../deep-research/slides/10-storm-demo.tsx | 51 +
.../deep-research/slides/11-limitation.tsx | 65 +
.../slides/12-diffusion-insight.tsx | 72 +
.../slides/13-diffusion-architecture.tsx | 21 +
.../slides/14-loop-visualized.tsx | 13 +
.../slides/15-parallel-agents.tsx | 17 +
.../slides/16-diffusion-demo.tsx | 46 +
.../deep-research/slides/17-benchmarks.tsx | 71 +
.../deep-research/slides/18-takeaways.tsx | 39 +
.../deep-research/slides/19-resources.tsx | 63 +
lib/presentations/deep-research.ts | 58 +
.../deep-research/demos/.env.example | 2 +
presentations/deep-research/demos/README.md | 113 +
.../deep-research/demos/diffusion_agent.py | 757 +++++++
presentations/deep-research/demos/log.py | 154 ++
presentations/deep-research/demos/main.py | 118 ++
.../deep-research/demos/pyproject.toml | 13 +
.../deep-research/demos/react_agent.py | 217 ++
.../deep-research/demos/storm_agent.py | 869 ++++++++
.../deep-research/demos/test_agents.py | 403 ++++
presentations/deep-research/demos/uv.lock | 1836 +++++++++++++++++
presentations/deep-research/outline.txt | 767 +++++++
presentations/deep-research/pitch.md | 9 +
presentations/deep-research/plan.md | 300 +++
.../deep-research/research/benchmarks.md | 239 +++
.../deep-research/research/diffusion.md | 353 ++++
.../deep-research/research/foo-cafe.md | 151 ++
.../deep-research/research/references.md | 217 ++
presentations/deep-research/research/storm.md | 260 +++
.../deep-research/research/timeline.md | 222 ++
presentations/deep-research/slides.md | 611 ++++++
presentations/deep-research/website-plan.md | 874 ++++++++
.../deep-research/logos/debricked-logo.png | Bin 0 -> 107731 bytes
.../deep-research/logos/oaiz-palm.png | Bin 0 -> 7329 bytes
.../deep-research/logos/podidex.png | Bin 0 -> 292415 bytes
.../deep-research/logos/valkompass.avif | Bin 0 -> 91570 bytes
.../plans/presentation-deep-research.md | 717 +++++++
...bsidian-iterative-research-architecture.md | 6 +-
...1_interactive-research-cli-architecture.md | 6 +-
...2-02_15-31-59_presentation-architecture.md | 505 +++++
60 files changed, 11502 insertions(+), 43 deletions(-)
create mode 100644 app/presentations/deep-research/[slide]/page.tsx
create mode 100644 app/presentations/deep-research/layout.tsx
create mode 100644 app/presentations/deep-research/page.tsx
create mode 100644 components/presentations/deep-research/slides/01-title.tsx
create mode 100644 components/presentations/deep-research/slides/02-group-project.tsx
create mode 100644 components/presentations/deep-research/slides/03-the-result.tsx
create mode 100644 components/presentations/deep-research/slides/04-the-reveal.tsx
create mode 100644 components/presentations/deep-research/slides/05-about.tsx
create mode 100644 components/presentations/deep-research/slides/06-audience-poll.tsx
create mode 100644 components/presentations/deep-research/slides/07-timeline.tsx
create mode 100644 components/presentations/deep-research/slides/08-cot.tsx
create mode 100644 components/presentations/deep-research/slides/08-storm-intro.tsx
create mode 100644 components/presentations/deep-research/slides/09-react-demo.tsx
create mode 100644 components/presentations/deep-research/slides/09-react.tsx
create mode 100644 components/presentations/deep-research/slides/09-storm-architecture.tsx
create mode 100644 components/presentations/deep-research/slides/10-storm-demo.tsx
create mode 100644 components/presentations/deep-research/slides/11-limitation.tsx
create mode 100644 components/presentations/deep-research/slides/12-diffusion-insight.tsx
create mode 100644 components/presentations/deep-research/slides/13-diffusion-architecture.tsx
create mode 100644 components/presentations/deep-research/slides/14-loop-visualized.tsx
create mode 100644 components/presentations/deep-research/slides/15-parallel-agents.tsx
create mode 100644 components/presentations/deep-research/slides/16-diffusion-demo.tsx
create mode 100644 components/presentations/deep-research/slides/17-benchmarks.tsx
create mode 100644 components/presentations/deep-research/slides/18-takeaways.tsx
create mode 100644 components/presentations/deep-research/slides/19-resources.tsx
create mode 100644 lib/presentations/deep-research.ts
create mode 100644 presentations/deep-research/demos/.env.example
create mode 100644 presentations/deep-research/demos/README.md
create mode 100644 presentations/deep-research/demos/diffusion_agent.py
create mode 100644 presentations/deep-research/demos/log.py
create mode 100644 presentations/deep-research/demos/main.py
create mode 100644 presentations/deep-research/demos/pyproject.toml
create mode 100644 presentations/deep-research/demos/react_agent.py
create mode 100644 presentations/deep-research/demos/storm_agent.py
create mode 100644 presentations/deep-research/demos/test_agents.py
create mode 100644 presentations/deep-research/demos/uv.lock
create mode 100644 presentations/deep-research/outline.txt
create mode 100644 presentations/deep-research/pitch.md
create mode 100644 presentations/deep-research/plan.md
create mode 100644 presentations/deep-research/research/benchmarks.md
create mode 100644 presentations/deep-research/research/diffusion.md
create mode 100644 presentations/deep-research/research/foo-cafe.md
create mode 100644 presentations/deep-research/research/references.md
create mode 100644 presentations/deep-research/research/storm.md
create mode 100644 presentations/deep-research/research/timeline.md
create mode 100644 presentations/deep-research/slides.md
create mode 100644 presentations/deep-research/website-plan.md
create mode 100644 public/presentations/deep-research/logos/debricked-logo.png
create mode 100644 public/presentations/deep-research/logos/oaiz-palm.png
create mode 100644 public/presentations/deep-research/logos/podidex.png
create mode 100644 public/presentations/deep-research/logos/valkompass.avif
create mode 100644 thoughts/shared/plans/presentation-deep-research.md
create mode 100644 thoughts/shared/research/2026-02-02_15-31-59_presentation-architecture.md
diff --git a/.gitignore b/.gitignore
index 18eb117..61139a3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -59,4 +59,5 @@ deep-research-agent/data/car_price_prediction_.csv
#
-go-research/external_code/
\ No newline at end of file
+go-research/external_code/
+**.pyc
diff --git a/app/presentations/deep-research/[slide]/page.tsx b/app/presentations/deep-research/[slide]/page.tsx
new file mode 100644
index 0000000..8882265
--- /dev/null
+++ b/app/presentations/deep-research/[slide]/page.tsx
@@ -0,0 +1,132 @@
+import { getAllSlideSlugs, getSlideBySlug } from '@/lib/presentations/deep-research';
+import { notFound } from 'next/navigation';
+import type { Metadata } from 'next';
+
+export const dynamic = 'error';
+export const revalidate = false;
+
+export async function generateStaticParams() {
+ return getAllSlideSlugs().map((slide) => ({ slide }));
+}
+
+export async function generateMetadata({
+ params,
+}: {
+ params: Promise<{ slide: string }>;
+}): Promise {
+ const { slide } = await params;
+ const slideData = getSlideBySlug(slide);
+ if (!slideData) return { title: 'Slide Not Found' };
+
+ return {
+ title: `${slideData.title} — Deep Research Agents`,
+ description: 'Deep Research Agents: Architecture Walkthrough — Foo Cafe Malmö, Feb 2026',
+ };
+}
+
+export default async function SlidePage({
+ params,
+}: {
+ params: Promise<{ slide: string }>;
+}) {
+ const { slide } = await params;
+ const slideData = getSlideBySlug(slide);
+ if (!slideData) notFound();
+
+ const slideContent = await (async () => {
+ switch (slide) {
+ case '01-title': {
+ const { TitleSlide } = await import('@/components/presentations/deep-research/slides/01-title');
+ return ;
+ }
+ case '02-group-project': {
+ const { GroupProjectSlide } = await import('@/components/presentations/deep-research/slides/02-group-project');
+ return ;
+ }
+ case '03-the-result': {
+ const { TheResultSlide } = await import('@/components/presentations/deep-research/slides/03-the-result');
+ return ;
+ }
+ case '04-the-reveal': {
+ const { TheRevealSlide } = await import('@/components/presentations/deep-research/slides/04-the-reveal');
+ return ;
+ }
+ case '05-about': {
+ const { AboutSlide } = await import('@/components/presentations/deep-research/slides/05-about');
+ return ;
+ }
+ case '06-audience-poll': {
+ const { AudiencePollSlide } = await import('@/components/presentations/deep-research/slides/06-audience-poll');
+ return ;
+ }
+ case '07-timeline': {
+ const { TimelineSlide } = await import('@/components/presentations/deep-research/slides/07-timeline');
+ return ;
+ }
+ case '08-cot': {
+ const { CotSlide } = await import('@/components/presentations/deep-research/slides/08-cot');
+ return ;
+ }
+ case '09-react': {
+ const { ReactSlide } = await import('@/components/presentations/deep-research/slides/09-react');
+ return ;
+ }
+ case '09-react-demo': {
+ const { ReactDemoSlide } = await import('@/components/presentations/deep-research/slides/09-react-demo');
+ return ;
+ }
+ case '08-storm-intro': {
+ const { StormIntroSlide } = await import('@/components/presentations/deep-research/slides/08-storm-intro');
+ return ;
+ }
+ case '09-storm-architecture': {
+ const { StormArchitectureSlide } = await import('@/components/presentations/deep-research/slides/09-storm-architecture');
+ return ;
+ }
+ case '10-storm-demo': {
+ const { StormDemoSlide } = await import('@/components/presentations/deep-research/slides/10-storm-demo');
+ return ;
+ }
+ case '11-limitation': {
+ const { LimitationSlide } = await import('@/components/presentations/deep-research/slides/11-limitation');
+ return ;
+ }
+ case '12-diffusion-insight': {
+ const { DiffusionInsightSlide } = await import('@/components/presentations/deep-research/slides/12-diffusion-insight');
+ return ;
+ }
+ case '13-diffusion-architecture': {
+ const { DiffusionArchitectureSlide } = await import('@/components/presentations/deep-research/slides/13-diffusion-architecture');
+ return ;
+ }
+ case '14-loop-visualized': {
+ const { LoopVisualizedSlide } = await import('@/components/presentations/deep-research/slides/14-loop-visualized');
+ return ;
+ }
+ case '15-parallel-agents': {
+ const { ParallelAgentsSlide } = await import('@/components/presentations/deep-research/slides/15-parallel-agents');
+ return ;
+ }
+ case '16-diffusion-demo': {
+ const { DiffusionDemoSlide } = await import('@/components/presentations/deep-research/slides/16-diffusion-demo');
+ return ;
+ }
+ case '17-benchmarks': {
+ const { BenchmarksSlide } = await import('@/components/presentations/deep-research/slides/17-benchmarks');
+ return ;
+ }
+ case '18-takeaways': {
+ const { TakeawaysSlide } = await import('@/components/presentations/deep-research/slides/18-takeaways');
+ return ;
+ }
+ case '19-resources': {
+ const { ResourcesSlide } = await import('@/components/presentations/deep-research/slides/19-resources');
+ return ;
+ }
+ default:
+ notFound();
+ }
+ })();
+
+ return slideContent;
+}
diff --git a/app/presentations/deep-research/layout.tsx b/app/presentations/deep-research/layout.tsx
new file mode 100644
index 0000000..9297e28
--- /dev/null
+++ b/app/presentations/deep-research/layout.tsx
@@ -0,0 +1,106 @@
+'use client';
+
+import { useRouter, usePathname } from 'next/navigation';
+import { useEffect, useState, useCallback, createContext, useContext } from 'react';
+import { motion, AnimatePresence } from 'framer-motion';
+import {
+ getAllSlides,
+ getSlideIndex,
+ getAdjacentSlugs,
+ getSlideSteps,
+} from '@/lib/presentations/deep-research';
+
+const SlideStepContext = createContext(0);
+
+export function useSlideStep() {
+ return useContext(SlideStepContext);
+}
+
+function SlideStepProvider({
+ pathname,
+ children,
+}: {
+ pathname: string;
+ children: React.ReactNode;
+}) {
+ const router = useRouter();
+ const currentSlug = pathname.split('/').pop() ?? '';
+ const { prev, next } = getAdjacentSlugs(currentSlug);
+ const maxSteps = getSlideSteps(currentSlug);
+ const [step, setStep] = useState(0);
+
+ const handleKeyDown = useCallback(
+ (e: KeyboardEvent) => {
+ if (e.key === 'ArrowRight' || e.key === ' ') {
+ e.preventDefault();
+ if (step < maxSteps) {
+ setStep((s) => s + 1);
+ } else if (next) {
+ router.push(`/presentations/deep-research/${next}`);
+ }
+ } else if (e.key === 'ArrowLeft') {
+ e.preventDefault();
+ if (step > 0) {
+ setStep((s) => s - 1);
+ } else if (prev) {
+ router.push(`/presentations/deep-research/${prev}`);
+ }
+ }
+ },
+ [step, maxSteps, router, prev, next],
+ );
+
+ useEffect(() => {
+ window.addEventListener('keydown', handleKeyDown);
+ return () => window.removeEventListener('keydown', handleKeyDown);
+ }, [handleKeyDown]);
+
+ return (
+
+ {children}
+
+ );
+}
+
+export default function PresentationLayout({ children }: { children: React.ReactNode }) {
+ const pathname = usePathname();
+ const slides = getAllSlides();
+ const currentSlug = pathname.split('/').pop() ?? '';
+ const currentIndex = getSlideIndex(currentSlug);
+
+ return (
+
+ {/* Progress bar */}
+
+
+ {/* Slide content with fade transition — key resets step state on route change */}
+
+
+
+ {children}
+
+
+
+
+ {/* Slide counter */}
+
+ {currentIndex + 1} / {slides.length}
+
+
+ );
+}
diff --git a/app/presentations/deep-research/page.tsx b/app/presentations/deep-research/page.tsx
new file mode 100644
index 0000000..c291cb7
--- /dev/null
+++ b/app/presentations/deep-research/page.tsx
@@ -0,0 +1,7 @@
+import { redirect } from 'next/navigation';
+
+export const dynamic = 'error';
+
+export default function PresentationIndex() {
+ redirect('/presentations/deep-research/01-title');
+}
diff --git a/app/status/page.tsx b/app/status/page.tsx
index 4346ae2..53ec21a 100644
--- a/app/status/page.tsx
+++ b/app/status/page.tsx
@@ -10,10 +10,10 @@ import { SpotifyCard } from './components/spotify-card';
export const revalidate = 14400; // 4 hours in seconds
export const metadata = {
- title: 'Status - Emil Wareus',
+ title: 'Status - Emil Wåreus',
description: "What I'm working on, listening to, and doing right now.",
openGraph: {
- title: 'Status - Emil Wareus',
+ title: 'Status - Emil Wåreus',
description: 'Real-time view into my current activities.',
url: 'https://addcommitpush.io/status',
images: [
@@ -27,7 +27,7 @@ export const metadata = {
},
twitter: {
card: 'summary_large_image',
- title: 'Status - Emil Wareus',
+ title: 'Status - Emil Wåreus',
description: 'Real-time view into my current activities.',
images: ['https://addcommitpush.io/og-status.png'],
},
diff --git a/components/animations/diffusion/diffusion-overview.tsx b/components/animations/diffusion/diffusion-overview.tsx
index 8293e54..c53bff1 100644
--- a/components/animations/diffusion/diffusion-overview.tsx
+++ b/components/animations/diffusion/diffusion-overview.tsx
@@ -10,9 +10,9 @@ interface DiffusionOverviewProps {
}
const diffusionLoopStages = [
- 'Identify Gaps → ask research questions',
- 'Conduct Research in parallel + citations',
- 'Refine Draft Report → assess completeness',
+ 'Supervisor identifies gaps → calls ConductResearch tool',
+ 'ReAct sub-agents search in parallel → compress findings',
+ 'Refine draft with evidence → supervisor assesses completeness',
];
// Per-phase dwell times (ms): brief, initial draft, diffusion loop (slower), final report (faster)
@@ -28,7 +28,7 @@ const phases: { label: string; icon: LucideIcon; text: string; isLoop?: boolean
{
label: 'Initial Draft',
icon: FilePenLine,
- text: 'Creates a noisy draft from model knowledge only—no external facts yet, just structure and placeholders.',
+ text: 'Creates a noisy draft from LLM knowledge only (high temperature)—no search yet, intentionally speculative.',
},
{
label: 'Diffusion Loop',
diff --git a/components/animations/diffusion/draft-denoising.tsx b/components/animations/diffusion/draft-denoising.tsx
index 76d74b9..dc4fffd 100644
--- a/components/animations/diffusion/draft-denoising.tsx
+++ b/components/animations/diffusion/draft-denoising.tsx
@@ -7,30 +7,31 @@ import { FilePenLine, FileCheck2 } from 'lucide-react';
const stages = [
{
- label: 'Bullets',
+ label: 'Noisy draft (LLM knowledge only)',
render: (
-
- Compare OpenAI, Anthropic, DeepMind safety pillars
- Pull 3–5 primary sources (2023–2025)
-
+
+ Foo Café is a [community space?] in Malmö
+ that hosts [tech events?] . They may have
+ connections to [startups?] ...
+
),
},
{
- label: 'Masked draft',
+ label: 'After research + refinement',
render: (
- The report covers [pillars] across labs,
- highlighting [methods] with citations to
- [sources] .
+ Foo Café is a community-driven tech space in Malmö founded in 2012. They host hack nights,
+ tech talks, and pitch evenings. [attendance?] {' '}
+ [Source: foocafe.org]
),
},
{
- label: 'Refined text',
+ label: 'Evidence-complete draft',
render: (
- OpenAI: RLHF + eval gates. Anthropic: Constitutional AI + red-team. DeepMind:
- interpretability + strict evals. Cited incidents and mitigations mapped to primary URLs.
+ Foo Café hosts ~300 events/year with 1,691 Meetup members. Weekly hack nights see ~84%
+ RSVP conversion. Topics: AI/ML, FinTech, Web Dev. [Source: meetup.com/foocafe]
),
},
@@ -47,15 +48,15 @@ export function DraftDenoising({ className }: DraftDenoisingProps) {
useEffect(() => {
if (!isInView) return;
- const isAtEnd = iteration >= 15;
- const delay = isAtEnd ? 5000 : 700; // 5s hold on 15/15 before restarting
+ const isAtEnd = iteration >= 8;
+ const delay = isAtEnd ? 5000 : 900; // 5s hold on 8/8 before restarting
- const id = setTimeout(() => setIteration((prev) => (prev >= 15 ? 1 : prev + 1)), delay);
+ const id = setTimeout(() => setIteration((prev) => (prev >= 8 ? 1 : prev + 1)), delay);
return () => clearTimeout(id);
}, [isInView, iteration]);
- const progress = Math.min(iteration / 15, 1);
- const stageIndex = Math.min(2, Math.floor((iteration - 1) / 5)); // 1-5, 6-10, 11-15
+ const progress = Math.min(iteration / 8, 1);
+ const stageIndex = Math.min(2, Math.floor((iteration - 1) / 3)); // 1-3, 4-5, 6-8
const stage = stages[stageIndex];
return (
@@ -112,8 +113,8 @@ export function DraftDenoising({ className }: DraftDenoisingProps) {
- Iteration {iteration || 1} / 15
+ Iteration {iteration || 1} / 8
{Math.round(progress * 100)}% denoised
diff --git a/components/animations/diffusion/parallel-agents.tsx b/components/animations/diffusion/parallel-agents.tsx
index 2ef8bba..aae0ab4 100644
--- a/components/animations/diffusion/parallel-agents.tsx
+++ b/components/animations/diffusion/parallel-agents.tsx
@@ -12,17 +12,17 @@ interface ParallelAgentsProps {
const agents = [
{
name: 'Sub-Agent 1',
- focus: 'Global or section-level query',
+ focus: 'ReAct loop: search + think',
topic: 'Topic A',
},
{
name: 'Sub-Agent 2',
- focus: 'Section-specific deep dive',
+ focus: 'ReAct loop: search + think',
topic: 'Topic B',
},
{
name: 'Sub-Agent 3',
- focus: 'Comparative or incident-focused',
+ focus: 'ReAct loop: search + think',
topic: 'Topic C',
},
];
@@ -349,22 +349,22 @@ export function ParallelAgents({ className }: ParallelAgentsProps) {
- 1. Assign: Supervisor generates research
- questions and delegates to sub-agents (max 3 parallel)
+ 1. Assign: Supervisor calls ConductResearch
+ tool to delegate topics (max 3 parallel)
- 2. Research: Sub-agents work independently with
- isolated contexts, return compressed findings
+ 2. Research: Each sub-agent runs a ReAct loop
+ (search + think), then compresses findings
- 3. Refine: Findings converge, draft updated with
- citations, completeness assessed
+ 3. Refine: Draft updated with evidence and
+ citations. Supervisor calls ResearchComplete when done.
diff --git a/components/presentations/deep-research/slides/01-title.tsx b/components/presentations/deep-research/slides/01-title.tsx
new file mode 100644
index 0000000..2bd0d7c
--- /dev/null
+++ b/components/presentations/deep-research/slides/01-title.tsx
@@ -0,0 +1,36 @@
+'use client';
+
+import { motion } from 'framer-motion';
+
+export function TitleSlide() {
+ return (
+
+
+ Learn to build Deep Research Agents
+
+
+
+ Malmö AI Devs · Slagthuset
+
+
+
+ Emil Wåreus · Feb 5, 2026
+
+
+ );
+}
diff --git a/components/presentations/deep-research/slides/02-group-project.tsx b/components/presentations/deep-research/slides/02-group-project.tsx
new file mode 100644
index 0000000..2f00ebc
--- /dev/null
+++ b/components/presentations/deep-research/slides/02-group-project.tsx
@@ -0,0 +1,54 @@
+'use client';
+
+import { motion } from 'framer-motion';
+import { useSlideStep } from '@/app/presentations/deep-research/layout';
+
+const people = [
+ { name: 'Sigrid', section: 'Intro' },
+ { name: 'Torbjörn', section: 'History' },
+ { name: 'Hjördis', section: 'Theory' },
+ { name: 'Gunnar', section: 'Conclusion' },
+];
+
+export function GroupProjectSlide() {
+ const step = useSlideStep();
+
+ return (
+
+
Remember group projects?
+
+
+
+ {people.map((person, i) => (
+
+
+ {person.name[0]}
+
+ {person.name}
+
+ {person.section}
+
+
+ ))}
+
+
+
+
+ {people.map((person) => (
+
+ ))}
+
+
+ “The Report” — 3hrs before deadline
+
+
+
+
+ );
+}
diff --git a/components/presentations/deep-research/slides/03-the-result.tsx b/components/presentations/deep-research/slides/03-the-result.tsx
new file mode 100644
index 0000000..ef38ac1
--- /dev/null
+++ b/components/presentations/deep-research/slides/03-the-result.tsx
@@ -0,0 +1,34 @@
+'use client';
+
+import { motion } from 'framer-motion';
+
+const items = [
+ 'Repetitive',
+ 'Inconsistent',
+ 'Different tones',
+ 'Varying quality',
+ 'Not the grade you wanted',
+];
+
+export function TheResultSlide() {
+ return (
+
+
The result?
+
+
+ {items.map((item, i) => (
+
+ ×
+ {item}
+
+ ))}
+
+
+ );
+}
diff --git a/components/presentations/deep-research/slides/04-the-reveal.tsx b/components/presentations/deep-research/slides/04-the-reveal.tsx
new file mode 100644
index 0000000..be18fb6
--- /dev/null
+++ b/components/presentations/deep-research/slides/04-the-reveal.tsx
@@ -0,0 +1,60 @@
+'use client';
+
+import { motion } from 'framer-motion';
+import { useSlideStep } from '@/app/presentations/deep-research/layout';
+
+const problems = [
+ "Can't see each other",
+ "Can't update the plan",
+ 'One shot — hope it works',
+];
+
+export function TheRevealSlide() {
+ const step = useSlideStep();
+
+ return (
+
+
+ This is exactly how most AI research agents work.
+
+
+
+ {['PLAN', 'PARALLEL SEARCH', 'MERGE'].map((label, i) => (
+
+
+ {label}
+
+ {i < 2 &&
→ }
+
+ ))}
+
+
+
= 1 ? 1 : 0 }}
+ transition={{ duration: 0.4 }}
+ className="flex flex-col items-center gap-3 mb-12"
+ >
+ {problems.map((problem) => (
+
+ {problem}
+
+ ))}
+
+
+
= 2 ? 1 : 0, y: step >= 2 ? 0 : 10 }}
+ transition={{ duration: 0.4 }}
+ className="text-2xl font-semibold text-primary neon-glow"
+ >
+ Today: How we fixed this.
+
+
+ );
+}
diff --git a/components/presentations/deep-research/slides/05-about.tsx b/components/presentations/deep-research/slides/05-about.tsx
new file mode 100644
index 0000000..731bbf5
--- /dev/null
+++ b/components/presentations/deep-research/slides/05-about.tsx
@@ -0,0 +1,180 @@
+'use client';
+
+import { motion } from 'framer-motion';
+import Image from 'next/image';
+
+interface Card {
+ content: React.ReactNode;
+ rotate: number;
+ x: number;
+ y: number;
+ bg: string;
+ border: string;
+ width: string;
+ delay: number;
+}
+
+const cards: Card[] = [
+ {
+ content: (
+
+
+ oaiz
+ Founder
+ AI automation platform
+ oaiz.io
+
+ ),
+ rotate: -4,
+ x: -540,
+ y: -200,
+ bg: 'bg-zinc-900',
+ border: 'border-zinc-700',
+ width: 'w-60',
+ delay: 0.15,
+ },
+ {
+ content: (
+
+
+
+
+
Founder
+
Application security with AI
+
exit 2022
+
debricked.com
+
+ ),
+ rotate: 5,
+ x: 280,
+ y: -200,
+ bg: 'bg-zinc-900',
+ border: 'border-zinc-700',
+ width: 'w-64',
+ delay: 0.25,
+ },
+ {
+ content: (
+
+
+ Valkompass
+ Creator
+ AI-powered Swedish political compass
+ Tech philanthropy
+ valkompass.ai
+
+ ),
+ rotate: -2,
+ x: -540,
+ y: 150,
+ bg: 'bg-zinc-900',
+ border: 'border-emerald-800/50',
+ width: 'w-60',
+ delay: 0.35,
+ },
+ {
+ content: (
+
+
+ Podidex
+ Creator
+ AI-powered podcast deep dives
+ Fun sideproject
+ podidex.com
+
+ ),
+ rotate: 3,
+ x: 300,
+ y: 100,
+ bg: 'bg-zinc-900',
+ border: 'border-zinc-700',
+ width: 'w-56',
+ delay: 0.45,
+ },
+ {
+ content: (
+
+ addcommitpush.io
+ blog & talks
+
+ ),
+ rotate: -6,
+ x: -110,
+ y: 180,
+ bg: 'bg-zinc-900',
+ border: 'border-primary/30',
+ width: 'w-56',
+ delay: 0.55,
+ },
+];
+
+export function AboutSlide() {
+ return (
+
+ {/* Center identity */}
+
+
+ EW
+
+ Emil Wåreus
+
+ Spaghetti coder, ML trainer, agent builder & cat owner
+
+
+
+ {/* Scattered cards */}
+ {cards.map((card, i) => (
+
+ {/* Tape strip */}
+
+ {card.content}
+
+ ))}
+
+ );
+}
diff --git a/components/presentations/deep-research/slides/06-audience-poll.tsx b/components/presentations/deep-research/slides/06-audience-poll.tsx
new file mode 100644
index 0000000..6b0cfa4
--- /dev/null
+++ b/components/presentations/deep-research/slides/06-audience-poll.tsx
@@ -0,0 +1,38 @@
+'use client';
+
+import { motion } from 'framer-motion';
+import { useSlideStep } from '@/app/presentations/deep-research/layout';
+
+const questions = [
+ 'Who has used ChatGPT/Claude/Gemini/... - deep research agents?',
+ 'Who has built or experimented with AI agents?',
+ 'Who trusts AI research reports?',
+];
+
+export function AudiencePollSlide() {
+ const step = useSlideStep();
+
+ return (
+
+
Quick Poll
+
+
+ {questions.map((question, i) => (
+
= i ? 1 : 0,
+ x: i === 0 || step >= i ? 0 : -20,
+ }}
+ transition={{ duration: 0.3, delay: i === 0 ? 0.2 : 0 }}
+ className="flex items-start gap-4"
+ >
+ {i + 1}.
+ {question}
+
+ ))}
+
+
+ );
+}
diff --git a/components/presentations/deep-research/slides/07-timeline.tsx b/components/presentations/deep-research/slides/07-timeline.tsx
new file mode 100644
index 0000000..269d66f
--- /dev/null
+++ b/components/presentations/deep-research/slides/07-timeline.tsx
@@ -0,0 +1,73 @@
+'use client';
+
+import { motion } from 'framer-motion';
+import { useSlideStep } from '@/app/presentations/deep-research/layout';
+
+const entries = [
+ { date: 'Jan 2022', label: 'Chain-of-Thought', star: true, url: 'https://arxiv.org/abs/2201.11903' },
+ { date: 'Oct 2022', label: 'ReAct', star: true, url: 'https://arxiv.org/abs/2210.03629' },
+ { date: 'Jul 2023', label: 'GPT Researcher', star: false, url: 'https://github.com/assafelovic/gpt-researcher' },
+ { date: 'Feb 2024', label: 'STORM', star: true, url: 'https://github.com/stanford-oval/storm' },
+ { date: 'Feb 2025', label: 'OpenAI Deep Research', star: false, url: 'https://openai.com/index/introducing-deep-research/' },
+ { date: 'Mar 2025', label: 'Perplexity Deep Research', star: false, url: 'https://www.perplexity.ai/hub/blog/introducing-perplexity-deep-research' },
+ { date: 'Jul 2025', label: 'Diffusion Deep Research', star: true, url: 'https://arxiv.org/abs/2502.12018' },
+];
+
+export function TimelineSlide() {
+ const step = useSlideStep();
+
+ return (
+
+
The Evolution of Research Agents
+
+
+ {/* Timeline line — vertically centered on the dots (dot is h-4 = 16px, center at 8px) */}
+
+
+
+
+
+
= 1 ? 1 : 0 }}
+ transition={{ duration: 0.4 }}
+ className="mt-16 px-8 py-4 rounded-lg bg-card border border-primary/30 text-center"
+ >
+
+ Single calls → Agents → Multi-agent →{' '}
+ Iterative
+
+
+
+ );
+}
diff --git a/components/presentations/deep-research/slides/08-cot.tsx b/components/presentations/deep-research/slides/08-cot.tsx
new file mode 100644
index 0000000..a0edd5f
--- /dev/null
+++ b/components/presentations/deep-research/slides/08-cot.tsx
@@ -0,0 +1,66 @@
+'use client';
+
+import { motion } from 'framer-motion';
+import { useSlideStep } from '@/app/presentations/deep-research/layout';
+
+export function CotSlide() {
+ const step = useSlideStep();
+
+ return (
+
+
+ Chain-of-Thought: Show Your Work
+
+
+
+ {/* Standard Prompt */}
+
+
Standard Prompt
+
+
+ “Roger has 5 tennis balls. He buys 2 cans of 3. How many does he have now?”
+
+
+ Answer:
+ 11
+
+
+
+
+ {/* CoT Prompt */}
+
= 1 ? 1 : 0, x: step >= 1 ? 0 : 20 }}
+ transition={{ duration: 0.5 }}
+ className="rounded-xl bg-card border border-primary/30 p-8"
+ >
+ With Chain-of-Thought
+
+
+ “Roger has 5 tennis balls. He buys 2 cans of 3. How many does he have now?
+ Let's think step by step.”
+
+
+
1. Roger starts with 5 balls
+
2. 2 cans × 3 balls = 6 new balls
+
3. 5 + 6 = 11
+
Answer: 11
+
+
+
+
+
+ {/* Bottom insight */}
+
= 2 ? 1 : 0 }}
+ transition={{ duration: 0.4 }}
+ className="mt-12 px-8 py-4 rounded-lg bg-card border border-primary/30 text-center max-w-3xl"
+ >
+
+ This simple trick is the foundation of every research agent that followed.
+
+
+
+ );
+}
diff --git a/components/presentations/deep-research/slides/08-storm-intro.tsx b/components/presentations/deep-research/slides/08-storm-intro.tsx
new file mode 100644
index 0000000..2c88591
--- /dev/null
+++ b/components/presentations/deep-research/slides/08-storm-intro.tsx
@@ -0,0 +1,69 @@
+'use client';
+
+import { motion } from 'framer-motion';
+import { useSlideStep } from '@/app/presentations/deep-research/layout';
+
+const experts = [
+ { role: 'Basic Fact Writer', question: 'What are the key facts?' },
+ { role: 'AI Ethics Scholar', question: 'What about responsible use?' },
+ { role: 'Community Organizer', question: 'What does the audience want?' },
+];
+
+const colors = ['border-primary/40', 'border-secondary/40', 'border-accent/40'];
+const bgColors = ['bg-primary/10', 'bg-secondary/10', 'bg-accent/10'];
+const textColors = ['text-primary', 'text-secondary', 'text-accent'];
+
+export function StormIntroSlide() {
+ const step = useSlideStep();
+
+ return (
+
+
+
STORM
+ Stanford 2024
+
+
+
+ S ynthesis of{' '}
+ T opic{' '}
+ O utlines through{' '}
+ R etrieval and{' '}
+ M ulti-perspective question asking
+
+
+
+ “Wikipedia articles are comprehensive because they synthesize
+ multiple expert viewpoints”
+
+
+
+ {experts.map((expert, i) => (
+
+
+ {expert.role[0]}
+
+ {expert.role}
+
+ “{expert.question}”
+
+
+ ))}
+
+
+
= 1 ? 1 : 0 }}
+ transition={{ duration: 0.4 }}
+ className="text-xl text-center max-w-2xl"
+ >
+ Different experts ask different questions → comprehensive coverage
+
+
+ );
+}
diff --git a/components/presentations/deep-research/slides/09-react-demo.tsx b/components/presentations/deep-research/slides/09-react-demo.tsx
new file mode 100644
index 0000000..3d17427
--- /dev/null
+++ b/components/presentations/deep-research/slides/09-react-demo.tsx
@@ -0,0 +1,46 @@
+'use client';
+
+import { motion } from 'framer-motion';
+
+export function ReactDemoSlide() {
+ return (
+
+
+ Live Demo: ReAct
+
+
+
+ Switch to terminal
+
+
+
+ uv run main.py --agent=react "I am giving a presentation at Foo Café in Malmö about deep research AI agents. Research the community and what they like, and tell me how to give a good presentation that the audience will like. Tailored to this community"
+
+
+
+ Watch: Think → Act → Observe → Repeat
+
+
+ );
+}
diff --git a/components/presentations/deep-research/slides/09-react.tsx b/components/presentations/deep-research/slides/09-react.tsx
new file mode 100644
index 0000000..5419ee2
--- /dev/null
+++ b/components/presentations/deep-research/slides/09-react.tsx
@@ -0,0 +1,89 @@
+'use client';
+
+import { motion } from 'framer-motion';
+import { useSlideStep } from '@/app/presentations/deep-research/layout';
+
+const traceLines = [
+ { phase: 'THINK', text: '"I need to find when WASM 2.0 was released"', color: 'text-primary' },
+ { phase: 'ACT', text: 'search("WebAssembly 2.0 release date")', color: 'text-secondary' },
+ { phase: 'OBSERVE', text: '"W3C published the recommendation April 2024"', color: 'text-accent' },
+ { phase: 'THINK', text: '"Now I can answer with a verified fact."', color: 'text-primary' },
+];
+
+export function ReactSlide() {
+ const step = useSlideStep();
+
+ return (
+
+
+ ReAct: Reasoning + Acting
+
+
+
+ {/* Loop diagram */}
+
+
+ {/* Arrows */}
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Think -> Act */}
+
+ {/* Act -> Observe */}
+
+ {/* Observe -> Think */}
+
+
+ {/* Nodes */}
+
+ Think
+
+
+ Act
+
+
+ Observe
+
+
+
+ {/* Example trace */}
+
+ {traceLines.map((line, i) => (
+
+ {line.phase}
+ {line.text}
+
+ ))}
+
+
+
+ {/* Bottom insight */}
+
= 1 ? 1 : 0 }}
+ transition={{ duration: 0.4 }}
+ className="mt-12 px-8 py-4 rounded-lg bg-card border border-primary/30 text-center max-w-3xl"
+ >
+
+ CoT gave LLMs reasoning. ReAct gave them hands. This is when LLMs became{' '}
+ agents .
+
+
+
+ );
+}
diff --git a/components/presentations/deep-research/slides/09-storm-architecture.tsx b/components/presentations/deep-research/slides/09-storm-architecture.tsx
new file mode 100644
index 0000000..dcaccc5
--- /dev/null
+++ b/components/presentations/deep-research/slides/09-storm-architecture.tsx
@@ -0,0 +1,244 @@
+'use client';
+
+import { motion } from 'framer-motion';
+import { useSlideStep } from '@/app/presentations/deep-research/layout';
+
+function DownArrow({ visible }: { visible: boolean }) {
+ return (
+
+
+
+
+
+ );
+}
+
+function Pill({ children, className = '' }: { children: React.ReactNode; className?: string }) {
+ return (
+
+ {children}
+
+ );
+}
+
+function Badge({ children }: { children: React.ReactNode }) {
+ return (
+
+ {children}
+
+ );
+}
+
+function PhaseCard({
+ number,
+ name,
+ colorClass,
+ borderClass,
+ bgClass,
+ visible,
+ delay = 0,
+ badge,
+ children,
+}: {
+ number: number;
+ name: string;
+ colorClass: string;
+ borderClass: string;
+ bgClass: string;
+ visible: boolean;
+ delay?: number;
+ badge?: string;
+ children: React.ReactNode;
+}) {
+ return (
+
+
+ {number}.
+ {name}
+ {badge && {badge} }
+
+ {children}
+
+ );
+}
+
+function MiniFlow({ items, colorClass }: { items: string[]; colorClass: string }) {
+ return (
+
+ {items.map((item, i) => (
+
+
{item}
+ {i < items.length - 1 &&
→ }
+
+ ))}
+
+ );
+}
+
+function ConversationLanes() {
+ const lanes = [
+ { perspective: 'Perspective 1', color: 'border-primary/30 bg-primary/5' },
+ { perspective: 'Perspective 2', color: 'border-secondary/30 bg-secondary/5' },
+ { perspective: 'Perspective 3', color: 'border-accent/30 bg-accent/5' },
+ ];
+
+ return (
+
+ {lanes.map((lane) => (
+
+
{lane.perspective}
+
+ Writer ↔ Expert
+
+
×3 turns
+
+ ))}
+
+ );
+}
+
+export function StormArchitectureSlide() {
+ const step = useSlideStep();
+
+ return (
+
+
STORM: Five Phases
+
+ S ynthesis of{' '}
+ T opic{' '}
+ O utlines through{' '}
+ R etrieval and{' '}
+ M ulti-perspective question asking
+
+
+
+ {/* Phase 1: DISCOVER — always visible (step 0) */}
+
+
+
+ Always includes a “Basic fact writer” — ensures broad factual coverage
+
+
+
+ {/* Arrow 1→2 */}
+
= 1} />
+
+ {/* Phase 2: INTERVIEW — step 1 */}
+ = 1}
+ badge="parallel"
+ >
+
+
+ TopicExpert: QuestionToQuery → Search → AnswerQuestion with [1],[2] citations
+
+
+
+ {/* Arrow 2→3 */}
+ = 2} />
+
+ {/* Phase 3: OUTLINE — step 2 */}
+ = 2}
+ >
+
+
+ Two-stage: structure from parametric knowledge, details from research
+
+
+
+ {/* Arrow 3→4 */}
+ = 2} />
+
+ {/* Phase 4: WRITE SECTIONS — step 2 with stagger */}
+ = 2}
+ delay={0.2}
+ >
+
+
+ Each top-level section written independently with collected snippets
+
+
+
+ {/* Arrow 4→5 */}
+ = 2} />
+
+ {/* Phase 5: LEAD + ASSEMBLE — step 2 with longer stagger */}
+ = 2}
+ delay={0.35}
+ >
+
+
+ Lead written last — it reflects actual content, not a guess
+
+
+
+
+ {/* Bottom callout — step 3 */}
+
= 3 ? 1 : 0, y: step >= 3 ? 0 : 10 }}
+ transition={{ duration: 0.4 }}
+ className="mt-6 px-6 py-3 rounded-lg border border-secondary/30 bg-secondary/5 text-center"
+ >
+
+ Linear pipeline — each phase runs exactly once . No backtracking.
+
+
+
+ );
+}
diff --git a/components/presentations/deep-research/slides/10-storm-demo.tsx b/components/presentations/deep-research/slides/10-storm-demo.tsx
new file mode 100644
index 0000000..1c83935
--- /dev/null
+++ b/components/presentations/deep-research/slides/10-storm-demo.tsx
@@ -0,0 +1,51 @@
+'use client';
+
+import { motion } from 'framer-motion';
+
+export function StormDemoSlide() {
+ return (
+
+
+ Live Demo: STORM
+
+
+
+ Switch to terminal
+
+
+
+ uv run main.py --agent=storm "I am giving a presentation at Foo Café in Malmö about deep research AI agents. Research the community and what they like, and tell me how to give a good presentation that the audience will like. Tailored to this community"
+
+
+
+
+ Watch: Perspectives → Parallel interviews (WikiWriter ↔ TopicExpert)
+
+
+ → Two-stage outline → Per-section writing → Lead + assembly
+
+
+
+ );
+}
diff --git a/components/presentations/deep-research/slides/11-limitation.tsx b/components/presentations/deep-research/slides/11-limitation.tsx
new file mode 100644
index 0000000..6ca5671
--- /dev/null
+++ b/components/presentations/deep-research/slides/11-limitation.tsx
@@ -0,0 +1,65 @@
+'use client';
+
+import { motion } from 'framer-motion';
+import { useSlideStep } from '@/app/presentations/deep-research/layout';
+
+const warnings = [
+ 'Still can\'t see each other',
+ 'Still one pass',
+ 'Still no self-correction',
+];
+
+const agentColors = ['border-primary/40 text-primary', 'border-secondary/40 text-secondary', 'border-accent/40 text-accent'];
+
+export function LimitationSlide() {
+ const step = useSlideStep();
+
+ return (
+
+
+ But there's still a problem...
+
+
+
+ {['Agent A', 'Agent B', 'Agent C'].map((agent, i) => (
+
+ {agent}
+
+ ))}
+
+
+
= 1 ? 1 : 0 }}
+ transition={{ duration: 0.4 }}
+ className="px-8 py-6 rounded-lg border-2 border-secondary/40 bg-secondary/5 mb-12"
+ >
+
+ {warnings.map((warning) => (
+
{warning}
+ ))}
+
+
+
+
= 2 ? 1 : 0, y: step >= 2 ? 0 : 10 }}
+ transition={{ duration: 0.4 }}
+ className="text-2xl font-semibold text-primary neon-glow"
+ >
+ What if the report could evolve?
+
+
+ );
+}
diff --git a/components/presentations/deep-research/slides/12-diffusion-insight.tsx b/components/presentations/deep-research/slides/12-diffusion-insight.tsx
new file mode 100644
index 0000000..0655a78
--- /dev/null
+++ b/components/presentations/deep-research/slides/12-diffusion-insight.tsx
@@ -0,0 +1,72 @@
+'use client';
+
+import { motion } from 'framer-motion';
+import { useSlideStep } from '@/app/presentations/deep-research/layout';
+
+export function DiffusionInsightSlide() {
+ const step = useSlideStep();
+
+ return (
+
+
+ What if research worked like image generation?
+
+
+
+ IMAGE DIFFUSION
+
+ {['Noise', 'Less Noise', 'Shape', 'Clean Image'].map((label, i) => (
+
+
+ {label}
+
+ {i < 3 &&
→ }
+
+ ))}
+
+
+
+
+ ↓ same idea ↓
+
+
+
+ RESEARCH DIFFUSION
+
+ {['Rough Draft', '+Gap Fill', 'Refine', 'Final Report'].map((label, i) => (
+
+
+ {label}
+
+ {i < 3 &&
→ }
+
+ ))}
+
+
+
+
= 1 ? 1 : 0 }}
+ transition={{ duration: 0.4 }}
+ className="text-xl font-semibold text-center text-primary neon-glow"
+ >
+ The initial draft IS the noise we refine away.
+
+
+ );
+}
diff --git a/components/presentations/deep-research/slides/13-diffusion-architecture.tsx b/components/presentations/deep-research/slides/13-diffusion-architecture.tsx
new file mode 100644
index 0000000..f7a2e55
--- /dev/null
+++ b/components/presentations/deep-research/slides/13-diffusion-architecture.tsx
@@ -0,0 +1,21 @@
+'use client';
+
+import { DiffusionOverview } from '@/components/animations/diffusion';
+
+export function DiffusionArchitectureSlide() {
+ return (
+
+
+
Diffusion Deep Research
+ Google 2025
+
+
+
+
+
+ Loop stops when EVIDENCE is complete,
+ not when draft looks good
+
+
+ );
+}
diff --git a/components/presentations/deep-research/slides/14-loop-visualized.tsx b/components/presentations/deep-research/slides/14-loop-visualized.tsx
new file mode 100644
index 0000000..11dbce4
--- /dev/null
+++ b/components/presentations/deep-research/slides/14-loop-visualized.tsx
@@ -0,0 +1,13 @@
+'use client';
+
+import { DraftDenoising } from '@/components/animations/diffusion';
+
+export function LoopVisualizedSlide() {
+ return (
+
+
The Draft Evolves
+
+
+
+ );
+}
diff --git a/components/presentations/deep-research/slides/15-parallel-agents.tsx b/components/presentations/deep-research/slides/15-parallel-agents.tsx
new file mode 100644
index 0000000..cde2f6d
--- /dev/null
+++ b/components/presentations/deep-research/slides/15-parallel-agents.tsx
@@ -0,0 +1,17 @@
+'use client';
+
+import { ParallelAgents } from '@/components/animations/diffusion';
+
+export function ParallelAgentsSlide() {
+ return (
+
+
Parallel Research, Isolated Contexts
+
+
+
+
+ Why isolated? Independent perspectives. No cross-contamination.
+
+
+ );
+}
diff --git a/components/presentations/deep-research/slides/16-diffusion-demo.tsx b/components/presentations/deep-research/slides/16-diffusion-demo.tsx
new file mode 100644
index 0000000..a0dee74
--- /dev/null
+++ b/components/presentations/deep-research/slides/16-diffusion-demo.tsx
@@ -0,0 +1,46 @@
+'use client';
+
+import { motion } from 'framer-motion';
+
+export function DiffusionDemoSlide() {
+ return (
+
+
+ Live Demo: Diffusion
+
+
+
+ Switch to terminal
+
+
+
+ uv run main.py --agent=diffusion "I am giving a presentation at Foo Café in Malmö about deep research AI agents. Research the community and what they like, and tell me how to give a good presentation that the audience will like. Tailored to this community"
+
+
+
+ Watch: Noisy draft → Gap detection → Parallel research → Refine → Repeat
+
+
+ );
+}
diff --git a/components/presentations/deep-research/slides/17-benchmarks.tsx b/components/presentations/deep-research/slides/17-benchmarks.tsx
new file mode 100644
index 0000000..1e5084f
--- /dev/null
+++ b/components/presentations/deep-research/slides/17-benchmarks.tsx
@@ -0,0 +1,71 @@
+'use client';
+
+import { motion } from 'framer-motion';
+
+const reasons = [
+ { factor: 'Iterative refinement', impact: 'Catches gaps single-pass misses' },
+ { factor: 'Evidence-based completion', impact: 'No premature stopping' },
+ { factor: 'Self-balancing', impact: 'Simple=2 iters, Complex=15' },
+ { factor: 'Isolated sub-agents', impact: 'Independent perspectives' },
+];
+
+export function BenchmarksSlide() {
+ return (
+
+ );
+}
diff --git a/components/presentations/deep-research/slides/18-takeaways.tsx b/components/presentations/deep-research/slides/18-takeaways.tsx
new file mode 100644
index 0000000..3a5aa47
--- /dev/null
+++ b/components/presentations/deep-research/slides/18-takeaways.tsx
@@ -0,0 +1,39 @@
+'use client';
+
+import { motion } from 'framer-motion';
+
+const takeaways = [
+ { title: 'Start with a draft', description: 'Even rough \u2014 reveals gaps faster than blank page' },
+ { title: 'Completion = evidence, not aesthetics', description: 'Stop when queries yield no new facts' },
+ { title: 'Information first, generation second', description: "Don't polish hallucinations" },
+ { title: 'Isolate sub-agent contexts', description: 'Context Engineering is key! Make sure that only high signal content make it to the main agent loop.' },
+ { title: 'Read the reports and verify references', description: 'Your human judgement > LLM as a judge/metrics.' },
+];
+
+export function TakeawaysSlide() {
+ return (
+
+
What You Can Apply Today
+
+
+ {takeaways.map((takeaway, i) => (
+
+
+ {i + 1}
+
+
+
{takeaway.title}
+
{takeaway.description}
+
+
+ ))}
+
+
+ );
+}
diff --git a/components/presentations/deep-research/slides/19-resources.tsx b/components/presentations/deep-research/slides/19-resources.tsx
new file mode 100644
index 0000000..9b07ddc
--- /dev/null
+++ b/components/presentations/deep-research/slides/19-resources.tsx
@@ -0,0 +1,63 @@
+'use client';
+
+import { motion } from 'framer-motion';
+
+const resources = [
+ {
+ label: 'Blog post (code walkthrough)',
+ url: 'addcommitpush.io/blog/diffusion-deep-research',
+ },
+ {
+ label: 'Reference implementation (Diffusion)',
+ url: 'github.com/thinkdepthai/Deep_Research',
+ },
+ {
+ label: 'STORM (Stanford)',
+ url: 'github.com/stanford-oval/storm',
+ },
+ {
+ label: 'DeepResearch Bench Leaderboard',
+ url: 'huggingface.co/spaces/muset-ai/DeepResearch-Bench-Leaderboard',
+ },
+];
+
+export function ResourcesSlide() {
+ return (
+
+
+ Questions?
+
+
+
+
+
+ Go Deeper
+
+
+ {resources.map((resource) => (
+
+ {resource.label}
+ {resource.url}
+
+ ))}
+
+
+
+
+
+ Emil Wåreus · addcommitpush.io
+
+
+
+ );
+}
diff --git a/lib/presentations/deep-research.ts b/lib/presentations/deep-research.ts
new file mode 100644
index 0000000..77d8108
--- /dev/null
+++ b/lib/presentations/deep-research.ts
@@ -0,0 +1,58 @@
+export interface Slide {
+ slug: string;
+ title: string;
+ steps: number;
+}
+
+const slides: Slide[] = [
+ { slug: '01-title', title: 'Learn to build Deep Research Agents', steps: 0 },
+ { slug: '02-group-project', title: 'The Group Project Problem', steps: 1 },
+ { slug: '03-the-result', title: 'The Result', steps: 0 },
+ { slug: '04-the-reveal', title: 'The AI Connection', steps: 2 },
+ { slug: '05-about', title: 'Emil Wåreus', steps: 0 },
+ { slug: '06-audience-poll', title: 'Quick Poll', steps: 2 },
+ { slug: '07-timeline', title: 'Evolution of Research Agents', steps: 1 },
+ { slug: '08-cot', title: 'Chain-of-Thought: Show Your Work', steps: 2 },
+ { slug: '09-react', title: 'ReAct: Reasoning + Acting', steps: 1 },
+ { slug: '09-react-demo', title: 'Live Demo: ReAct', steps: 0 },
+ { slug: '08-storm-intro', title: 'STORM: Multi-Perspective Research', steps: 1 },
+ { slug: '09-storm-architecture', title: 'STORM: Four Phases', steps: 3 },
+ { slug: '10-storm-demo', title: 'Live Demo: STORM', steps: 0 },
+ { slug: '11-limitation', title: 'The Problem with Linear Pipelines', steps: 2 },
+ { slug: '12-diffusion-insight', title: 'Research as Diffusion', steps: 1 },
+ { slug: '13-diffusion-architecture', title: 'Diffusion Deep Research', steps: 0 },
+ { slug: '14-loop-visualized', title: 'The Draft Evolves', steps: 0 },
+ { slug: '15-parallel-agents', title: 'Parallel Research, Isolated Contexts', steps: 0 },
+ { slug: '16-diffusion-demo', title: 'Live Demo: Diffusion', steps: 0 },
+ { slug: '17-benchmarks', title: 'Why Diffusion Wins', steps: 0 },
+ { slug: '18-takeaways', title: 'What You Can Apply Today', steps: 0 },
+ { slug: '19-resources', title: 'Questions & Resources', steps: 0 },
+];
+
+export function getAllSlides(): Slide[] {
+ return slides;
+}
+
+export function getSlideBySlug(slug: string): Slide | null {
+ return slides.find((s) => s.slug === slug) ?? null;
+}
+
+export function getAllSlideSlugs(): string[] {
+ return slides.map((s) => s.slug);
+}
+
+export function getSlideIndex(slug: string): number {
+ return slides.findIndex((s) => s.slug === slug);
+}
+
+export function getAdjacentSlugs(slug: string): { prev: string | null; next: string | null } {
+ const idx = getSlideIndex(slug);
+ return {
+ prev: idx > 0 ? slides[idx - 1].slug : null,
+ next: idx < slides.length - 1 ? slides[idx + 1].slug : null,
+ };
+}
+
+export function getSlideSteps(slug: string): number {
+ return slides.find((s) => s.slug === slug)?.steps ?? 0;
+}
diff --git a/presentations/deep-research/demos/.env.example b/presentations/deep-research/demos/.env.example
new file mode 100644
index 0000000..800e44d
--- /dev/null
+++ b/presentations/deep-research/demos/.env.example
@@ -0,0 +1,2 @@
+OPENROUTER_API_KEY=sk-or-v1-your-key-here
+TAVILY_API_KEY=tvly-your-key-here
diff --git a/presentations/deep-research/demos/README.md b/presentations/deep-research/demos/README.md
new file mode 100644
index 0000000..a30e14b
--- /dev/null
+++ b/presentations/deep-research/demos/README.md
@@ -0,0 +1,113 @@
+# Deep Research Demo Agents
+
+Three self-contained LangGraph agent implementations for live demo purposes.
+Each demonstrates a different approach to AI-powered research.
+
+## Setup
+
+```bash
+cd presentations/deep-research/demos
+
+# Install dependencies
+uv sync
+
+# Add your API keys to .env
+cp .env.example .env
+# Edit .env with your keys
+```
+
+### Required environment variables
+
+| Variable | Source |
+|----------|--------|
+| `OPENROUTER_API_KEY` | [openrouter.ai/keys](https://openrouter.ai/keys) |
+| `TAVILY_API_KEY` | [app.tavily.com](https://app.tavily.com/) |
+
+## Usage
+
+```bash
+uv run main.py --agent=
"your query"
+```
+
+### ReAct — Think-Act-Observe loop
+
+The foundational agent pattern (Yao et al., 2022). The LLM reasons about what to do,
+calls a search tool, observes the result, and repeats until it has an answer.
+
+```bash
+uv run main.py --agent=react "Who is the president of the United States?"
+uv run main.py --agent=react "What is the latest version of Python?"
+```
+
+**Speed:** Fast (~10s). Best for simple factual queries.
+
+**Graph:**
+```
+START -> agent -> [tool calls?] -> tools -> agent (loop)
+ [no calls] -> END
+```
+
+### STORM — Multi-perspective research
+
+Stanford's 4-phase pipeline (2024). Generates multiple expert perspectives,
+runs parallel interviews with web search, creates an outline, and writes a report.
+
+```bash
+uv run main.py --agent=storm "The impact of large language models on software engineering"
+uv run main.py --agent=storm "Comparison of React, Vue, and Svelte in 2026"
+```
+
+**Speed:** Medium (~60-90s). Runs 3 parallel expert interviews.
+
+**Graph:**
+```
+START -> discover_perspectives -> conduct_interview (x3 parallel)
+ -> generate_outline -> write_report -> END
+```
+
+### Diffusion — Iterative draft refinement
+
+Google's iterative approach (2025). Starts with a "noisy" draft from LLM knowledge,
+then repeatedly identifies gaps, researches them in parallel, and refines the draft.
+
+```bash
+uv run main.py --agent=diffusion "How do modern CPUs handle branch prediction?"
+uv run main.py --agent=diffusion "The state of quantum computing in 2026"
+```
+
+**Speed:** Slower (~2-3 min). Runs up to 3 refinement iterations.
+
+**Graph:**
+```
+START -> generate_brief -> generate_noisy_draft -> identify_gaps
+ -> research_sub_agent (xN parallel) -> refine_draft
+ -> [comprehensive?] -> identify_gaps (loop)
+ -> [done] -> generate_report -> END
+```
+
+## Architecture overview
+
+| Agent | Paper | Key idea | LangGraph features used |
+|-------|-------|----------|------------------------|
+| ReAct | Yao et al. 2022 | Think-Act-Observe loop | Conditional edges, ToolNode |
+| STORM | Stanford 2024 | Multi-perspective interviews | `Send()` fan-out, subgraphs, structured output |
+| Diffusion | Google 2025 | Iterative noise-to-signal refinement | `Send()` fan-out, `operator.add` reducers, loop control |
+
+## Model
+
+All agents use `google/gemini-3-flash-preview` via OpenRouter. To change the model,
+edit the `ChatOpenAI(model=...)` line in each agent file.
+
+## File structure
+
+```
+demos/
+ .env # API keys (git-ignored)
+ pyproject.toml # uv project config
+ main.py # CLI entry point
+ react_agent.py # ReAct implementation
+ storm_agent.py # STORM implementation
+ diffusion_agent.py # Diffusion implementation
+```
+
+Each agent file is self-contained with heavy comments explaining the architecture.
diff --git a/presentations/deep-research/demos/diffusion_agent.py b/presentations/deep-research/demos/diffusion_agent.py
new file mode 100644
index 0000000..954f7f6
--- /dev/null
+++ b/presentations/deep-research/demos/diffusion_agent.py
@@ -0,0 +1,757 @@
+"""
+Diffusion Deep Research Agent — Faithful implementation of thinkdepthai/Deep_Research
+=====================================================================================
+
+This is a 1-to-1 reimplementation of the diffusion-based deep research system from
+https://github.com/thinkdepthai/Deep_Research — consolidated into a single file with
+detailed walkthrough comments and demo-friendly logging.
+
+The core idea from the paper: treat research like image diffusion. Start with a "noisy"
+draft (written from LLM knowledge only, no search), then iteratively "denoise" it by:
+1. Having a supervisor identify what research is needed
+2. Dispatching sub-agents that do ReAct-style search loops
+3. Compressing their findings
+4. Refining the draft with the new evidence
+5. Repeating until the supervisor is satisfied
+
+Architecture (matches reference):
+ START → write_research_brief → write_draft_report
+ → supervisor ↔ supervisor_tools (loop)
+ - ConductResearch → research_agent (ReAct sub-agent)
+ - refine_draft_report → updates draft
+ - think_tool → reflection
+ - ResearchComplete → done
+ → final_report_generation → END
+
+Key concepts from the reference:
+- Supervisor LLM with tool-calling decides WHAT to research and WHEN to stop
+- Sub-agents use ReAct pattern (LLM + search tool + think tool in a loop)
+- Research is compressed before returning to supervisor (information preservation)
+- Draft is refined with each batch of findings (the "denoising" step)
+- Final report is a polished version of the refined draft
+"""
+
+import operator
+import os
+from datetime import datetime
+from typing import Annotated, Literal, Sequence
+
+from langchain_openai import ChatOpenAI
+from langchain_core.messages import (
+ AIMessage,
+ BaseMessage,
+ HumanMessage,
+ SystemMessage,
+ ToolMessage,
+ filter_messages,
+)
+from langchain_core.tools import tool
+from langgraph.graph import StateGraph, START, END
+from langgraph.graph.message import add_messages
+from langgraph.types import Command
+from pydantic import BaseModel, Field
+from tavily import TavilyClient
+from typing_extensions import TypedDict
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ LLM CONFIGURATION ║
+# ║ ║
+# ║ Using OpenRouter to route to Groq for fastest inference. ║
+# ║ The reference uses gpt-5; we use gpt-oss-120b for demo speed. ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+llm = ChatOpenAI(
+ model="openai/gpt-oss-120b",
+ base_url="https://openrouter.ai/api/v1",
+ api_key=os.environ["OPENROUTER_API_KEY"],
+ temperature=0,
+ extra_body={"provider": {"order": ["Groq"]}},
+)
+
+# Higher temperature for the "noisy" initial draft — more speculative
+llm_creative = ChatOpenAI(
+ model="openai/gpt-oss-120b",
+ base_url="https://openrouter.ai/api/v1",
+ api_key=os.environ["OPENROUTER_API_KEY"],
+ temperature=0.7,
+ extra_body={"provider": {"order": ["Groq"]}},
+)
+
+# Direct Tavily client for proper URL extraction (not the langchain wrapper)
+tavily_client = TavilyClient(api_key=os.environ["TAVILY_API_KEY"])
+
+
+def get_today_str() -> str:
+ return datetime.now().strftime("%a %b %-d, %Y")
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ TOOLS — matching the reference's tool definitions ║
+# ║ ║
+# ║ Reference has: tavily_search, think_tool, ConductResearch, ║
+# ║ ResearchComplete, refine_draft_report ║
+# ║ ║
+# ║ tavily_search: used by sub-agents to search the web ║
+# ║ think_tool: used by both supervisor and sub-agents for reflection ║
+# ║ ConductResearch: supervisor delegates research to sub-agents ║
+# ║ ResearchComplete: supervisor signals research is done ║
+# ║ refine_draft_report: supervisor triggers draft refinement ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+
+@tool(parse_docstring=True)
+def tavily_search(query: str) -> str:
+ """Search the web for information on a topic.
+
+ Args:
+ query: A search query to execute
+
+ Returns:
+ Formatted search results with sources and content
+ """
+ import log
+
+ log.search(query)
+ results = tavily_client.search(
+ query, max_results=3, include_raw_content=False
+ )
+
+ formatted = "Search results:\n\n"
+ for i, result in enumerate(results.get("results", []), 1):
+ url = result.get("url", "")
+ title = result.get("title", "")
+ content = result.get("content", "")
+ formatted += f"--- SOURCE {i}: {title} ---\n"
+ formatted += f"URL: {url}\n\n"
+ formatted += f"{content}\n\n"
+ formatted += "-" * 40 + "\n"
+ log.detail(f"Source {i}: {url}")
+
+ return formatted
+
+
+@tool(parse_docstring=True)
+def think_tool(reflection: str) -> str:
+ """Strategic reflection on research progress and decision-making.
+
+ Use after each search to analyze results and plan next steps.
+
+ Args:
+ reflection: Your detailed reflection on research progress
+
+ Returns:
+ Confirmation that reflection was recorded
+ """
+ import log
+ log.thinking(f"Reflection: {reflection[:120]}...")
+ return f"Reflection recorded: {reflection}"
+
+
+# Supervisor tools — these are Pydantic models used as tool schemas
+@tool
+class ConductResearch(BaseModel):
+ """Delegate a research task to a specialized sub-agent that will search the web."""
+ research_topic: str = Field(
+ description="The topic to research. Should be described in detail."
+ )
+
+
+@tool
+class ResearchComplete(BaseModel):
+ """Signal that research is complete and all findings have been gathered."""
+ pass
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ STATE DEFINITIONS — matching the reference's state schemas ║
+# ║ ║
+# ║ Reference has: ║
+# ║ - ResearcherState: for sub-agent ReAct loops ║
+# ║ - SupervisorState: for the supervisor's tool-calling loop ║
+# ║ - AgentState: for the full pipeline ║
+# ║ ║
+# ║ We merge these into two: ResearcherState + DiffusionState ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+
+class ResearcherState(TypedDict):
+ """State for each sub-agent's ReAct research loop."""
+ researcher_messages: Annotated[Sequence[BaseMessage], add_messages]
+ research_topic: str
+ compressed_research: str
+ raw_notes: Annotated[list[str], operator.add]
+
+
+class DiffusionState(TypedDict):
+ """Main pipeline state — combines AgentState + SupervisorState from reference."""
+ query: str
+ research_brief: str
+ draft_report: str
+ supervisor_messages: Annotated[Sequence[BaseMessage], add_messages]
+ notes: Annotated[list[str], operator.add]
+ raw_notes: Annotated[list[str], operator.add]
+ research_iterations: int
+ final_report: str
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ PHASE 1: RESEARCH BRIEF ║
+# ║ ║
+# ║ Reference: research_agent_scope.py → write_research_brief() ║
+# ║ Converts user query into a detailed, structured research brief. ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+
+RESEARCH_BRIEF_PROMPT = """You will be given a user request. Your job is to translate it into a detailed research brief.
+
+User request: {query}
+
+Today's date is {date}.
+
+Guidelines:
+1. Maximize specificity — include all key dimensions to investigate
+2. Avoid unwarranted assumptions — note unspecified aspects as open
+3. Use first person — phrase from the user's perspective
+4. Be specific about what sources to prioritize
+
+Return a single, detailed research brief."""
+
+
+def write_research_brief(state: DiffusionState) -> dict:
+ """Phase 1: Convert user query into structured research brief."""
+ import log
+
+ query = state["query"]
+ log.phase("Phase 1: Write Research Brief")
+ log.step("*", "Converting query into detailed research brief...")
+
+ prompt = RESEARCH_BRIEF_PROMPT.format(query=query, date=get_today_str())
+ response = llm.invoke([HumanMessage(content=prompt)])
+ log.track_cost(response.response_metadata)
+
+ log.success(f"Brief generated ({len(response.content)} chars)")
+ for line in response.content.strip().split("\n")[:4]:
+ if line.strip():
+ log.detail(line.strip())
+
+ return {"research_brief": response.content}
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ PHASE 2: NOISY DRAFT ║
+# ║ ║
+# ║ Reference: research_agent_scope.py → write_draft_report() ║
+# ║ The "noise" — a draft from LLM knowledge ONLY, no search. ║
+# ║ Higher temperature encourages speculative content that will be ║
+# ║ verified/corrected by real research in subsequent phases. ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+
+DRAFT_REPORT_PROMPT = """Based on your knowledge, create a comprehensive draft report for:
+
+{research_brief}
+
+Today's date is {date}.
+
+Write a detailed draft with proper headings and sections.
+This is an initial draft — it will be refined with actual research.
+Be thorough but acknowledge where you're uncertain.
+
+Format in clear markdown with ## section headers."""
+
+
+def write_draft_report(state: DiffusionState) -> dict:
+ """Phase 2: Generate noisy draft from LLM knowledge only (no search)."""
+ import log
+
+ brief = state["research_brief"]
+ log.phase("Phase 2: Write Draft Report (LLM knowledge only)")
+ log.step("*", "Generating initial draft — no search, temperature=0.7")
+
+ prompt = DRAFT_REPORT_PROMPT.format(research_brief=brief, date=get_today_str())
+ response = llm_creative.invoke([HumanMessage(content=prompt)])
+ log.track_cost(response.response_metadata)
+
+ log.success(f"Draft generated ({len(response.content)} chars)")
+
+ # Pass draft + brief to supervisor as initial messages
+ return {
+ "draft_report": response.content,
+ "supervisor_messages": [
+ HumanMessage(content=f"Here is the draft report: {response.content}\n\n{brief}")
+ ],
+ }
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ SUB-AGENT: RESEARCH AGENT (ReAct pattern) ║
+# ║ ║
+# ║ Reference: research_agent.py ║
+# ║ Each sub-agent runs a ReAct loop: LLM → tool calls → LLM → ... ║
+# ║ Uses tavily_search for web search and think_tool for reflection. ║
+# ║ Results are compressed before returning to the supervisor. ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+
+RESEARCH_AGENT_PROMPT = """You are a research assistant. Today's date is {date}.
+
+Use the search tool to gather information about the topic. After each search,
+use think_tool to reflect on what you found and what's still missing.
+
+Hard limits:
+- Use 2-5 search tool calls maximum
+- Stop when you have 3+ relevant sources
+- Stop if last 2 searches returned similar information
+
+After gathering enough info, provide a comprehensive answer with citations."""
+
+research_tools = [tavily_search, think_tool]
+research_tools_by_name = {t.name: t for t in research_tools}
+llm_with_research_tools = llm.bind_tools(research_tools)
+
+
+def research_llm_call(state: ResearcherState) -> dict:
+ """Sub-agent Think step: LLM decides to search or answer."""
+ import log
+
+ messages = state["researcher_messages"]
+ topic = state.get("research_topic", "")
+
+ prompt = RESEARCH_AGENT_PROMPT.format(date=get_today_str())
+ response = llm_with_research_tools.invoke(
+ [SystemMessage(content=prompt)] + list(messages)
+ )
+ log.track_cost(response.response_metadata)
+
+ if response.tool_calls:
+ for tc in response.tool_calls:
+ name = tc.get("name", "")
+ args = tc.get("args", {})
+ if name == "tavily_search":
+ log.step(">", f"Sub-agent searching: {args.get('query', '')[:80]}")
+ elif name == "think_tool":
+ log.step("?", "Sub-agent reflecting...")
+ else:
+ log.success(f"Sub-agent done ({len(response.content)} chars)")
+
+ return {"researcher_messages": [response]}
+
+
+def research_tool_node(state: ResearcherState) -> dict:
+ """Sub-agent Act step: execute all tool calls."""
+ last_msg = state["researcher_messages"][-1]
+ tool_outputs = []
+ for tc in last_msg.tool_calls:
+ tool_fn = research_tools_by_name[tc["name"]]
+ observation = tool_fn.invoke(tc["args"])
+ tool_outputs.append(
+ ToolMessage(content=observation, name=tc["name"], tool_call_id=tc["id"])
+ )
+ return {"researcher_messages": tool_outputs}
+
+
+def compress_research(state: ResearcherState) -> dict:
+ """Compress research findings into a concise summary with citations.
+
+ Instead of passing raw conversation messages (which confuse models when
+ they contain ToolMessages), we extract the text content from tool and AI
+ messages and pass it as a single prompt.
+ """
+ import log
+
+ messages = state["researcher_messages"]
+ topic = state.get("research_topic", "")
+
+ log.step("=", f"Compressing research on: {topic[:60]}")
+
+ # Extract text content from tool messages (search results) and AI messages
+ raw_notes = []
+ for m in messages:
+ if hasattr(m, "content") and m.content:
+ if hasattr(m, "name") and m.name == "tavily_search":
+ raw_notes.append(m.content)
+ elif hasattr(m, "name") and m.name == "think_tool":
+ continue # Skip think_tool reflections
+ elif isinstance(m, ToolMessage):
+ raw_notes.append(m.content)
+ elif isinstance(m, AIMessage) and m.content:
+ raw_notes.append(m.content)
+
+ findings_text = "\n\n---\n\n".join(raw_notes)
+
+ prompt = f"""Clean up these research findings. Preserve ALL information and source URLs.
+
+Research topic: {topic}
+
+Raw findings:
+{findings_text}
+
+Rules:
+- Preserve ALL relevant information verbatim
+- Include ALL source URLs as [Source: URL] citations
+- Remove duplicates
+- Structure: Cleaned findings with inline citations, then a Sources section listing all URLs
+
+Return the cleaned findings."""
+
+ response = llm.invoke([HumanMessage(content=prompt)])
+ log.track_cost(response.response_metadata)
+
+ log.success(f"Compressed to {len(response.content)} chars")
+ return {
+ "compressed_research": str(response.content),
+ "raw_notes": ["\n".join(str(n) for n in raw_notes)],
+ }
+
+
+def research_should_continue(state: ResearcherState) -> Literal["research_tool_node", "compress_research"]:
+ """Route: if LLM made tool calls → execute them, else → compress."""
+ last_msg = state["researcher_messages"][-1]
+ if last_msg.tool_calls:
+ return "research_tool_node"
+ return "compress_research"
+
+
+# Build and compile the sub-agent graph (ReAct loop)
+_research_builder = StateGraph(ResearcherState)
+_research_builder.add_node("research_llm_call", research_llm_call)
+_research_builder.add_node("research_tool_node", research_tool_node)
+_research_builder.add_node("compress_research", compress_research)
+_research_builder.add_edge(START, "research_llm_call")
+_research_builder.add_conditional_edges(
+ "research_llm_call",
+ research_should_continue,
+ {"research_tool_node": "research_tool_node", "compress_research": "compress_research"},
+)
+_research_builder.add_edge("research_tool_node", "research_llm_call")
+_research_builder.add_edge("compress_research", END)
+research_agent = _research_builder.compile()
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ SUPERVISOR — the diffusion loop controller ║
+# ║ ║
+# ║ Reference: multi_agent_supervisor.py ║
+# ║ The supervisor LLM decides what to research next using tools: ║
+# ║ - ConductResearch: spawn a sub-agent for a specific topic ║
+# ║ - refine_draft_report: update the draft with findings ║
+# ║ - think_tool: reflect on progress ║
+# ║ - ResearchComplete: signal we're done ║
+# ║ ║
+# ║ This loop IS the diffusion denoising — each iteration reduces ║
+# ║ uncertainty in the draft by replacing speculation with evidence. ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+MAX_SUPERVISOR_ITERATIONS = 8
+MAX_CONCURRENT_RESEARCHERS = 3
+
+SUPERVISOR_PROMPT = """You are a research supervisor. Today's date is {date}.
+You follow the diffusion algorithm to iteratively improve a draft report.
+
+Diffusion Algorithm:
+1. Identify gaps in the draft report that need research
+2. Call ConductResearch to gather evidence for those gaps
+3. Call refine_draft_report to update the draft with new findings
+4. Repeat until findings are comprehensive
+5. Call ResearchComplete when done
+
+Available tools:
+- ConductResearch: Delegate research to a sub-agent (max {max_concurrent} parallel)
+- refine_draft_report: Refine the draft with collected findings
+- think_tool: Reflect on progress and plan next steps
+- ResearchComplete: Signal research is complete
+
+IMPORTANT:
+- Use think_tool before and after ConductResearch calls
+- Always call refine_draft_report after ConductResearch
+- Each ConductResearch spawns an independent agent — give it full context
+- Stop after gathering comprehensive findings, not when draft "looks good"
+- Limit to {max_iterations} total tool-call rounds"""
+
+supervisor_tools = [ConductResearch, ResearchComplete, think_tool]
+supervisor_tools_by_name = {"think_tool": think_tool}
+llm_with_supervisor_tools = llm.bind_tools(supervisor_tools)
+
+
+def _get_notes_from_tool_calls(messages: Sequence[BaseMessage]) -> list[str]:
+ """Extract compressed research findings from ToolMessage objects."""
+ return [
+ tm.content
+ for tm in filter_messages(messages, include_types="tool")
+ ]
+
+
+def supervisor(state: DiffusionState) -> Command[Literal["supervisor_tools"]]:
+ """Supervisor decides next action: research, refine, think, or complete."""
+ import log
+
+ supervisor_messages = list(state.get("supervisor_messages", []))
+ iteration = state.get("research_iterations", 0) + 1
+
+ log.phase(f"Supervisor (iteration {iteration}/{MAX_SUPERVISOR_ITERATIONS})")
+
+ system_msg = SUPERVISOR_PROMPT.format(
+ date=get_today_str(),
+ max_concurrent=MAX_CONCURRENT_RESEARCHERS,
+ max_iterations=MAX_SUPERVISOR_ITERATIONS,
+ )
+ messages = [SystemMessage(content=system_msg)] + supervisor_messages
+ response = llm_with_supervisor_tools.invoke(messages)
+ log.track_cost(response.response_metadata)
+
+ if response.tool_calls:
+ for tc in response.tool_calls:
+ log.step(">", f"Supervisor calls: {tc['name']}")
+ if tc["name"] == "ConductResearch":
+ log.detail(f"Topic: {tc['args'].get('research_topic', '')[:80]}")
+ else:
+ log.step("=", "Supervisor provided text response (no tool calls)")
+
+ return Command(
+ goto="supervisor_tools",
+ update={
+ "supervisor_messages": [response],
+ "research_iterations": iteration,
+ },
+ )
+
+
+def _refine_draft(state: DiffusionState) -> str:
+ """Refine the draft report using collected findings."""
+ import log
+
+ notes = _get_notes_from_tool_calls(state.get("supervisor_messages", []))
+ findings = "\n".join(notes)
+ draft = state.get("draft_report", "")
+ brief = state.get("research_brief", "")
+
+ log.step("*", "Refining draft report with new findings...")
+
+ prompt = f"""Refine this draft report using the new research findings.
+
+Research Brief:
+{brief}
+
+Current Draft:
+{draft}
+
+New Findings:
+{findings}
+
+Rules:
+- Integrate verified facts from findings into the draft
+- Add proper [Source: URL] citations
+- Correct any claims contradicted by research
+- Keep the overall structure
+- Write in markdown with ## section headers
+
+Return the complete updated draft."""
+
+ response = llm.invoke([HumanMessage(content=prompt)])
+ log.track_cost(response.response_metadata)
+ log.success(f"Draft refined ({len(response.content)} chars)")
+ return response.content
+
+
+def supervisor_tools_node(state: DiffusionState) -> Command[Literal["supervisor", "final_report_generation"]]:
+ """Execute supervisor's tool calls — research, refine, think, or complete."""
+ import log
+
+ supervisor_messages = list(state.get("supervisor_messages", []))
+ iteration = state.get("research_iterations", 0)
+ last_msg = supervisor_messages[-1]
+
+ # ── Exit conditions ──
+ exceeded = iteration >= MAX_SUPERVISOR_ITERATIONS
+ no_tools = not last_msg.tool_calls
+ research_complete = any(
+ tc["name"] == "ResearchComplete" for tc in (last_msg.tool_calls or [])
+ )
+
+ if exceeded or no_tools or research_complete:
+ if exceeded:
+ log.success(f"Max iterations ({MAX_SUPERVISOR_ITERATIONS}) reached → finalizing")
+ elif research_complete:
+ log.success("Supervisor called ResearchComplete → finalizing")
+ else:
+ log.success("No more tool calls → finalizing")
+
+ return Command(
+ goto="final_report_generation",
+ update={
+ "notes": _get_notes_from_tool_calls(supervisor_messages),
+ "research_brief": state.get("research_brief", ""),
+ },
+ )
+
+ # ── Execute tool calls ──
+ tool_messages: list[ToolMessage] = []
+ all_raw_notes: list[str] = []
+ new_draft = ""
+
+ # Separate tool call types
+ think_calls = [tc for tc in last_msg.tool_calls if tc["name"] == "think_tool"]
+ research_calls = [tc for tc in last_msg.tool_calls if tc["name"] == "ConductResearch"]
+ # refine is handled automatically after research
+
+ # Handle think_tool calls
+ for tc in think_calls:
+ observation = think_tool.invoke(tc["args"])
+ tool_messages.append(
+ ToolMessage(content=observation, name=tc["name"], tool_call_id=tc["id"])
+ )
+
+ # Handle ConductResearch calls — run sub-agents
+ if research_calls:
+ log.step("*", f"Launching {len(research_calls)} research sub-agent(s)...")
+
+ results = []
+ for tc in research_calls:
+ topic = tc["args"]["research_topic"]
+ log.divider()
+ log.step("*", f"Sub-agent: {topic[:70]}")
+
+ result = research_agent.invoke({
+ "researcher_messages": [HumanMessage(content=topic)],
+ "research_topic": topic,
+ "compressed_research": "",
+ "raw_notes": [],
+ })
+ results.append(result)
+
+ # Format results as tool messages (this is how supervisor gets the findings)
+ for result, tc in zip(results, research_calls):
+ compressed = result.get("compressed_research", "No findings.")
+ tool_messages.append(
+ ToolMessage(content=compressed, name=tc["name"], tool_call_id=tc["id"])
+ )
+ all_raw_notes.append("\n".join(result.get("raw_notes", [])))
+ log.result("Research", compressed[:150])
+
+ # After research, always refine the draft (matching reference behavior)
+ log.divider()
+ log.phase("Refine Draft (denoising step)")
+
+ # Temporarily add research tool messages so _refine_draft can access them
+ temp_state = dict(state)
+ temp_state["supervisor_messages"] = list(supervisor_messages) + tool_messages
+ new_draft = _refine_draft(temp_state)
+
+ if new_draft:
+ return Command(
+ goto="supervisor",
+ update={
+ "supervisor_messages": tool_messages,
+ "raw_notes": all_raw_notes,
+ "draft_report": new_draft,
+ },
+ )
+ else:
+ return Command(
+ goto="supervisor",
+ update={
+ "supervisor_messages": tool_messages,
+ "raw_notes": all_raw_notes,
+ },
+ )
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ PHASE 5: FINAL REPORT ║
+# ║ ║
+# ║ Reference: research_agent_full.py → final_report_generation() ║
+# ║ Polish the refined draft into a professional final report. ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+
+FINAL_REPORT_PROMPT = """Based on the research conducted and draft report, create a comprehensive final report.
+
+Research Brief:
+{research_brief}
+
+Draft Report:
+{draft_report}
+
+Research Findings:
+{findings}
+
+Today's date is {date}.
+
+Create a detailed report that:
+1. Has proper headings (## for sections)
+2. Includes specific facts and insights from the research
+3. References sources with [Source: URL] citations
+4. Provides thorough analysis
+5. Ends with a Sources section listing all URLs
+
+Write in paragraph form, not bullet points. Be comprehensive."""
+
+
+def final_report_generation(state: DiffusionState) -> dict:
+ """Phase 5: Polish the refined draft into the final report."""
+ import log
+
+ notes = state.get("notes", [])
+ findings = "\n".join(notes)
+ draft = state.get("draft_report", "")
+ brief = state.get("research_brief", "")
+
+ log.phase("Phase 5: Final Report Generation")
+ log.step("*", f"Polishing with {len(notes)} research notes...")
+
+ prompt = FINAL_REPORT_PROMPT.format(
+ research_brief=brief,
+ draft_report=draft,
+ findings=findings,
+ date=get_today_str(),
+ )
+ response = llm.invoke([HumanMessage(content=prompt)])
+ log.track_cost(response.response_metadata)
+
+ log.success(f"Final report: {len(response.content)} chars")
+ return {"final_report": response.content}
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ GRAPH ASSEMBLY ║
+# ║ ║
+# ║ Reference pipeline: ║
+# ║ clarify → brief → draft → supervisor ↔ tools → final report ║
+# ║ We skip clarify (demo doesn't need it, reference skips it too). ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+builder = StateGraph(DiffusionState)
+
+builder.add_node("write_research_brief", write_research_brief)
+builder.add_node("write_draft_report", write_draft_report)
+builder.add_node("supervisor", supervisor)
+builder.add_node("supervisor_tools", supervisor_tools_node)
+builder.add_node("final_report_generation", final_report_generation)
+
+builder.add_edge(START, "write_research_brief")
+builder.add_edge("write_research_brief", "write_draft_report")
+builder.add_edge("write_draft_report", "supervisor")
+# supervisor ↔ supervisor_tools is handled by Command routing
+builder.add_edge("final_report_generation", END)
+
+graph = builder.compile()
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ ENTRY POINT HELPER ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+
+def initial_state(query: str) -> DiffusionState:
+ """Build the starting state for the Diffusion agent."""
+ return {
+ "query": query,
+ "research_brief": "",
+ "draft_report": "",
+ "supervisor_messages": [],
+ "notes": [],
+ "raw_notes": [],
+ "research_iterations": 0,
+ "final_report": "",
+ }
diff --git a/presentations/deep-research/demos/log.py b/presentations/deep-research/demos/log.py
new file mode 100644
index 0000000..768f5b8
--- /dev/null
+++ b/presentations/deep-research/demos/log.py
@@ -0,0 +1,154 @@
+"""
+Shared logging helpers for demo agents.
+
+Provides clear, structured console output so a live audience
+can follow what each agent is doing step-by-step.
+"""
+
+import textwrap
+import threading
+import time
+from contextlib import contextmanager
+
+# ANSI colors
+DIM = "\033[2m"
+BOLD = "\033[1m"
+CYAN = "\033[36m"
+GREEN = "\033[32m"
+YELLOW = "\033[33m"
+MAGENTA = "\033[35m"
+BLUE = "\033[34m"
+RESET = "\033[0m"
+
+
+# ── Cost tracking ──────────────────────────────────────────────────────
+# Thread-safe accumulator for OpenRouter costs.
+
+_cost_lock = threading.Lock()
+_total_cost: float = 0.0
+_total_calls: int = 0
+
+
+def track_cost(response_metadata: dict) -> float:
+ """Extract and accumulate cost from an OpenRouter response.
+
+ OpenRouter returns cost in response_metadata["token_usage"]["cost"].
+ Returns the cost for this call.
+ """
+ global _total_cost, _total_calls
+
+ cost = 0.0
+
+ # OpenRouter puts cost inside token_usage
+ token_usage = response_metadata.get("token_usage", {})
+ if isinstance(token_usage, dict):
+ cost = token_usage.get("cost", 0.0) or 0.0
+
+ with _cost_lock:
+ _total_cost += cost
+ _total_calls += 1
+
+ return cost
+
+
+def get_total_cost() -> tuple[float, int]:
+ """Return (total_cost, total_calls)."""
+ with _cost_lock:
+ return _total_cost, _total_calls
+
+
+def reset_cost() -> None:
+ """Reset cost tracking for a new run."""
+ global _total_cost, _total_calls
+ with _cost_lock:
+ _total_cost = 0.0
+ _total_calls = 0
+
+
+# ── Display helpers ────────────────────────────────────────────────────
+
+
+def header(agent_name: str, query: str) -> None:
+ """Print the agent run header."""
+ reset_cost()
+ print(f"\n{BOLD}{'=' * 64}{RESET}")
+ print(f"{BOLD} {agent_name}{RESET}")
+ print(f" Query: {DIM}{query}{RESET}")
+ print(f"{BOLD}{'=' * 64}{RESET}\n")
+
+
+def phase(label: str) -> None:
+ """Print a major phase separator."""
+ print(f"\n{BOLD}{CYAN}--- {label} ---{RESET}\n")
+
+
+def step(icon: str, msg: str) -> None:
+ """Print a single step within a phase."""
+ print(f" {icon} {msg}")
+
+
+def detail(msg: str) -> None:
+ """Print an indented detail line."""
+ print(f" {DIM}{msg}{RESET}")
+
+
+def thinking(msg: str) -> None:
+ """Print a 'thinking' indicator."""
+ print(f" {YELLOW}?{RESET} {msg}")
+
+
+def success(msg: str) -> None:
+ """Print a success indicator."""
+ print(f" {GREEN}+{RESET} {msg}")
+
+
+def search(query: str) -> None:
+ """Log a search operation."""
+ print(f" {MAGENTA}>{RESET} Searching: {DIM}{query[:80]}{RESET}")
+
+
+def result(label: str, content: str, max_len: int = 120) -> None:
+ """Print a result summary, truncated."""
+ truncated = content.replace("\n", " ")[:max_len]
+ if len(content) > max_len:
+ truncated += "..."
+ print(f" {GREEN}={RESET} {label}: {truncated}")
+
+
+def divider() -> None:
+ """Print a light divider."""
+ print(f" {DIM}{'- ' * 30}{RESET}")
+
+
+@contextmanager
+def timed(_label: str = ""):
+ """Context manager that prints elapsed time for a block."""
+ start = time.time()
+ yield
+ elapsed = time.time() - start
+ print(f" {DIM}({elapsed:.1f}s){RESET}")
+
+
+def conversation(role: str, analyst_name: str, content: str, width: int = 72) -> None:
+ """Print a conversation message in a chat-bubble style."""
+ if role == "WikiWriter":
+ color = YELLOW
+ label = f"{analyst_name} (WikiWriter)"
+ else:
+ color = GREEN
+ label = f"TopicExpert -> {analyst_name}"
+
+ print(f" {color}{BOLD}{label}{RESET}")
+ # Wrap the content to fit nicely in the terminal
+ wrapped = textwrap.fill(content, width=width, initial_indent=" ", subsequent_indent=" ")
+ print(f"{DIM}{wrapped}{RESET}")
+ print()
+
+
+def final_report_header() -> None:
+ """Print the final report separator."""
+ total_cost, total_calls = get_total_cost()
+ print(f"\n{BOLD}{'=' * 64}{RESET}")
+ print(f"{BOLD} FINAL REPORT{RESET}")
+ print(f" {DIM}Total cost: ${total_cost:.4f} across {total_calls} LLM calls{RESET}")
+ print(f"{BOLD}{'=' * 64}{RESET}\n")
diff --git a/presentations/deep-research/demos/main.py b/presentations/deep-research/demos/main.py
new file mode 100644
index 0000000..fbdb5f2
--- /dev/null
+++ b/presentations/deep-research/demos/main.py
@@ -0,0 +1,118 @@
+"""
+CLI entry point for Deep Research demo agents.
+
+Usage:
+ uv run main.py --agent=react "Who is the president of the United States?"
+ uv run main.py --agent=storm "Who is the president of the United States?"
+ uv run main.py --agent=diffusion "Who is the president of the United States?"
+
+Each agent demonstrates a different approach to AI-powered research:
+- react: Classic Think-Act-Observe loop (ReAct, Yao et al. 2022)
+- storm: Multi-perspective research pipeline (STORM, Stanford 2024)
+- diffusion: Iterative draft refinement (Diffusion Deep Research, Google 2025)
+"""
+
+import argparse
+import re
+import time
+from pathlib import Path
+
+from dotenv import load_dotenv
+
+AGENT_LABELS = {
+ "react": "ReAct Agent (Think-Act-Observe)",
+ "storm": "STORM Agent (Multi-Perspective Research)",
+ "diffusion": "Diffusion Agent (Iterative Refinement)",
+}
+
+
+def main() -> None:
+ # Load .env from the demos directory (next to this file)
+ load_dotenv(Path(__file__).parent / ".env")
+
+ import log
+
+ parser = argparse.ArgumentParser(
+ description="Run Deep Research demo agents",
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ epilog=__doc__,
+ )
+ parser.add_argument(
+ "--agent",
+ choices=["react", "storm", "diffusion"],
+ required=True,
+ help="Which agent architecture to run",
+ )
+ parser.add_argument(
+ "query",
+ type=str,
+ help="The research query to investigate",
+ )
+ args = parser.parse_args()
+
+ # ── Import the selected agent's compiled graph ──────────────────────
+ # Each module exposes a `graph` object (compiled LangGraph StateGraph)
+ # and an `initial_state(query)` function to build the starting state.
+
+ if args.agent == "react":
+ from react_agent import graph, initial_state
+ elif args.agent == "storm":
+ from storm_agent import graph, initial_state
+ else:
+ from diffusion_agent import graph, initial_state
+
+ # ── Stream execution ────────────────────────────────────────────────
+
+ log.header(AGENT_LABELS[args.agent], args.query)
+
+ state = initial_state(args.query)
+ config = {"recursion_limit": 100}
+
+ start = time.time()
+
+ # stream_mode="values" yields the full state after each node completes.
+ # The last yielded value IS the final state.
+ final_state = state
+ for update in graph.stream(state, config=config, stream_mode="values"):
+ final_state = update
+
+ elapsed = time.time() - start
+
+ # ── Print the final result ──────────────────────────────────────────
+
+ log.final_report_header()
+
+ if args.agent == "react":
+ last_msg = final_state["messages"][-1]
+ print(last_msg.content)
+ else:
+ print(final_state.get("final_report", "No report generated."))
+
+ # ── Extract source count per agent type ───────────────────────────
+ sources: set[str] = set()
+
+ if args.agent == "react":
+ # Extract URLs from ToolMessage content (search results)
+ from langchain_core.messages import ToolMessage
+ for msg in final_state.get("messages", []):
+ if isinstance(msg, ToolMessage):
+ sources.update(re.findall(r'https?://[^\s"\'\]>]+', msg.content))
+
+ elif args.agent == "storm":
+ # STORM tracks collected_urls explicitly
+ for url in final_state.get("collected_urls", []):
+ sources.add(url)
+
+ elif args.agent == "diffusion":
+ # Extract [Source: URL] citations from notes and final report
+ for note in final_state.get("notes", []):
+ sources.update(re.findall(r'https?://[^\s"\'\]>]+', note))
+ report = final_state.get("final_report", "")
+ sources.update(re.findall(r'https?://[^\s"\'\]>]+', report))
+
+ total_cost, total_calls = log.get_total_cost()
+ print(f"\n{log.DIM}Completed in {elapsed:.1f}s | Total LLM cost: ${total_cost:.4f} | LLM calls: {total_calls} | Sources: {len(sources)}{log.RESET}\n")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/presentations/deep-research/demos/pyproject.toml b/presentations/deep-research/demos/pyproject.toml
new file mode 100644
index 0000000..0eae442
--- /dev/null
+++ b/presentations/deep-research/demos/pyproject.toml
@@ -0,0 +1,13 @@
+[project]
+name = "deep-research-demos"
+version = "0.1.0"
+requires-python = ">=3.11"
+dependencies = [
+ "langgraph>=0.2.0",
+ "langchain-openai>=0.3.0",
+ "langchain-tavily>=0.1.0",
+ "tavily-python>=0.5.0",
+ "pydantic>=2.0",
+ "python-dotenv>=1.0.0",
+ "pytest>=8.0",
+]
diff --git a/presentations/deep-research/demos/react_agent.py b/presentations/deep-research/demos/react_agent.py
new file mode 100644
index 0000000..858f0f1
--- /dev/null
+++ b/presentations/deep-research/demos/react_agent.py
@@ -0,0 +1,217 @@
+"""
+ReAct Agent — Think-Act-Observe loop (Yao et al., 2022)
+========================================================
+
+This is the foundational pattern behind every modern research agent.
+The LLM reasons about what to do (Think), calls a tool (Act), observes the
+result (Observe), and repeats until it can produce a final answer.
+
+Graph structure:
+ START → agent → [has tool calls?] → tools → agent (loop)
+ [no tool calls?] → END
+
+Key concepts demonstrated:
+- Chain-of-Thought (CoT) reasoning via system prompt
+- Tool binding: attaching tool schemas to the LLM so it can request calls
+- The Think→Act→Observe cycle as a while-loop in graph form
+- Why this pattern is the foundation for STORM and Diffusion agents
+"""
+
+import os
+from typing import Annotated
+
+from langchain_openai import ChatOpenAI
+from langchain_tavily import TavilySearch
+from langchain_core.messages import SystemMessage
+from langgraph.graph import StateGraph, START, END
+from langgraph.graph.message import add_messages
+from langgraph.prebuilt import ToolNode
+from typing_extensions import TypedDict
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ LLM CONFIGURATION ║
+# ║ ║
+# ║ We use OpenRouter as a unified gateway to different LLM providers. ║
+# ║ Provider routing sends requests to Groq for fastest inference. ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+llm = ChatOpenAI(
+ model="openai/gpt-oss-120b",
+ base_url="https://openrouter.ai/api/v1",
+ api_key=os.environ["OPENROUTER_API_KEY"],
+ temperature=0,
+ extra_body={"provider": {"order": ["Groq"]}},
+)
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ TOOLS ║
+# ║ ║
+# ║ Tavily is a search API built specifically for AI agents. ║
+# ║ Unlike raw Google search, it returns clean extracted content ║
+# ║ rather than HTML snippets — much better for LLM consumption. ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+search_tool = TavilySearch(max_results=3)
+tools = [search_tool]
+
+# Bind tools to the LLM. This tells the LLM what tools are available
+# and their parameter schemas. The LLM can then output structured
+# "tool call" messages requesting specific tool invocations.
+llm_with_tools = llm.bind_tools(tools)
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ STATE DEFINITION ║
+# ║ ║
+# ║ LangGraph uses typed state that flows between nodes. Each node ║
+# ║ returns a partial state update that gets merged into the full ║
+# ║ state. ║
+# ║ ║
+# ║ The `add_messages` annotation means message lists are APPENDED, ║
+# ║ not overwritten. This preserves the full conversation history. ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+
+class ReActState(TypedDict):
+ messages: Annotated[list, add_messages]
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ SYSTEM PROMPT ║
+# ║ ║
+# ║ This prompt instructs the LLM to follow the ReAct pattern: ║
+# ║ 1. THINK about what information is needed ║
+# ║ 2. ACT by calling a search tool ║
+# ║ 3. OBSERVE the results and decide next steps ║
+# ║ 4. Repeat until confident, then give a final answer ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+SYSTEM_PROMPT = """You are a research assistant that follows the ReAct pattern:
+
+1. THINK: Reason about what information you need
+2. ACT: Use the search tool to find that information
+3. OBSERVE: Analyze what you found
+4. REPEAT or ANSWER: Either search for more, or give your final answer
+
+Always think step-by-step. When you have enough information, provide a
+clear, well-sourced answer. Cite your sources."""
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ GRAPH NODES ║
+# ║ ║
+# ║ A "node" is a Python function that receives state and returns a ║
+# ║ partial state update. Nodes are the building blocks of the graph. ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+
+def agent(state: ReActState) -> dict:
+ """
+ The 'Think' step. The LLM sees the full conversation history and
+ either:
+ (a) Generates a tool call → routes to 'tools' node (Act step)
+ (b) Generates a text response → routes to END (final answer)
+
+ This is where Chain-of-Thought reasoning happens. The LLM's internal
+ reasoning determines whether more information is needed.
+ """
+ import log
+
+ turn = len([m for m in state["messages"] if hasattr(m, "tool_calls") and m.tool_calls])
+ log.step("*", f"THINK (loop {turn + 1})")
+ log.detail("Sending conversation to LLM...")
+
+ messages = [SystemMessage(content=SYSTEM_PROMPT)] + state["messages"]
+ with log.timed("LLM call"):
+ response = llm_with_tools.invoke(messages)
+
+ log.track_cost(response.response_metadata)
+
+ if response.tool_calls:
+ for tc in response.tool_calls:
+ query = tc.get("args", {}).get("query", str(tc.get("args", "")))
+ log.thinking(f"Decided to search: \"{query}\"")
+ else:
+ log.success("Generated final answer")
+ log.detail(f"{len(response.content)} chars")
+
+ return {"messages": [response]}
+
+
+# The ToolNode is a built-in LangGraph component that:
+# 1. Reads tool_calls from the last AI message
+# 2. Executes each requested tool
+# 3. Returns ToolMessage(s) with the results
+# This is the 'Act' step — executing the tool the LLM requested.
+tool_node = ToolNode(tools)
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ ROUTING LOGIC ║
+# ║ ║
+# ║ The router decides whether to loop back (more research needed) ║
+# ║ or finish (answer is ready). This is the key control flow that ║
+# ║ makes ReAct a loop rather than a single pass. ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+
+def should_continue(state: ReActState) -> str:
+ """
+ Check if the LLM wants to call more tools.
+
+ If the last message has tool_calls → route to 'tools' (continue loop)
+ If the last message is plain text → route to END (answer is ready)
+
+ This is what makes ReAct iterative: the LLM can do multiple rounds
+ of search before committing to a final answer.
+ """
+ import log
+
+ last_message = state["messages"][-1]
+ if last_message.tool_calls:
+ log.step(">", "ACT Executing tool calls...")
+ return "tools"
+ log.step("=", "ANSWER Ready — routing to END")
+ return END
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ GRAPH ASSEMBLY ║
+# ║ ║
+# ║ We wire the nodes together into a directed graph. ║
+# ║ The conditional edge from 'agent' creates the loop. ║
+# ║ ║
+# ║ Visual: ║
+# ║ START → agent ──[tool calls]──→ tools ──→ agent (loop back) ║
+# ║ └─[no calls]───→ END ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+builder = StateGraph(ReActState)
+
+# Add nodes
+builder.add_node("agent", agent)
+builder.add_node("tools", tool_node)
+
+# Wire the graph
+builder.add_edge(START, "agent")
+builder.add_conditional_edges("agent", should_continue, ["tools", END])
+builder.add_edge("tools", "agent") # After tool execution, go back to agent
+
+# Compile into a runnable graph
+graph = builder.compile()
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ ENTRY POINT HELPER ║
+# ║ ║
+# ║ Creates the initial state from a user query. ║
+# ║ Used by main.py to standardize how all agents are invoked. ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+
+def initial_state(query: str) -> ReActState:
+ """Build the starting state for the ReAct agent."""
+ from langchain_core.messages import HumanMessage
+ return {"messages": [HumanMessage(content=query)]}
diff --git a/presentations/deep-research/demos/storm_agent.py b/presentations/deep-research/demos/storm_agent.py
new file mode 100644
index 0000000..248eec3
--- /dev/null
+++ b/presentations/deep-research/demos/storm_agent.py
@@ -0,0 +1,869 @@
+"""
+STORM Agent — Faithful reimplementation of Stanford STORM (2024)
+=================================================================
+
+Reference: https://github.com/stanford-oval/storm
+Paper: "Assisting in Writing Wikipedia-like Articles From Scratch
+ with Large Language Models" (Shao et al., 2024)
+
+STORM = Synthesis of Topic Outlines through Retrieval and Multi-perspective
+question asking. The core insight: Wikipedia articles are comprehensive because
+they synthesize MULTIPLE expert viewpoints. STORM simulates this by:
+
+1. Discovering what perspectives are needed (via related topic structure)
+2. Running multi-turn conversations between WikiWriter personas and a
+ search-grounded TopicExpert
+3. Building an outline in two stages (draft from knowledge, refine with data)
+4. Writing the article per-section with inline citations
+5. Adding a lead section and polishing
+
+Architecture (matches reference):
+ START → discover_perspectives → conduct_interviews (×N parallel via Send)
+ → generate_outline (2-stage) → write_sections (per-section parallel)
+ → write_lead_section → END
+
+Key architectural decisions from the reference:
+- Perspectives are generated from RELATED TOPIC STRUCTURE, not hallucinated
+- TopicExpert generates search queries FIRST, then searches, then answers
+- Outline is drafted from LLM knowledge, THEN refined with conversation data
+- Article is written PER-SECTION, not as one giant prompt
+- Lead section is written AFTER the body (so it reflects actual content)
+- The pipeline is LINEAR — no backtracking, each phase runs exactly once
+"""
+
+import operator
+import os
+from typing import Annotated, Literal
+
+from langchain_openai import ChatOpenAI
+from langchain_core.messages import (
+ AIMessage,
+ HumanMessage,
+ SystemMessage,
+)
+from langgraph.types import Send
+from langgraph.graph import StateGraph, START, END
+from pydantic import BaseModel, Field
+from tavily import TavilyClient
+from typing_extensions import TypedDict
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ LLM + SEARCH CONFIGURATION ║
+# ║ ║
+# ║ Reference uses 5 separate models (conv, question, outline, ║
+# ║ article, polish). We use one fast model for demo speed. ║
+# ║ Reference supports many search backends; we use Tavily directly. ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+llm = ChatOpenAI(
+ model="openai/gpt-oss-120b",
+ base_url="https://openrouter.ai/api/v1",
+ api_key=os.environ["OPENROUTER_API_KEY"],
+ temperature=0,
+ extra_body={"provider": {"order": ["Groq"]}},
+)
+
+tavily_client = TavilyClient(api_key=os.environ["TAVILY_API_KEY"])
+
+# ── Configuration matching reference defaults ──
+MAX_PERSPECTIVES = 3 # Reference default: 3 (plus 1 default "Basic fact writer")
+MAX_CONV_TURNS = 3 # Reference default: 3 turns per conversation
+MAX_SEARCH_QUERIES = 3 # Reference default: 3 queries per expert answer
+SEARCH_TOP_K = 3 # Reference default: 3 results per query
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ PYDANTIC MODELS — STRUCTURED OUTPUT ║
+# ║ ║
+# ║ Reference uses DSPy signatures. We use Pydantic with ║
+# ║ with_structured_output() for the same typed extraction. ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+
+class Analyst(BaseModel):
+ """One expert perspective/persona for researching the topic."""
+ name: str = Field(description="Short summary of the editor persona")
+ description: str = Field(description="Detailed description of their expertise and angle")
+
+
+class Perspectives(BaseModel):
+ """Generated expert perspectives based on related topic analysis."""
+ analysts: list[Analyst] = Field(
+ description="Expert personas, each representing a different perspective"
+ )
+
+
+class SearchQueries(BaseModel):
+ """Search queries generated from a conversation question."""
+ queries: list[str] = Field(
+ description="1-3 search queries to find information for answering the question"
+ )
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ STATE DEFINITIONS ║
+# ║ ║
+# ║ STORMState: main pipeline state ║
+# ║ InterviewState: per-conversation state for WikiWriter ↔ TopicExpert ║
+# ║ ║
+# ║ interview_results uses operator.add — when parallel interviews ║
+# ║ complete via Send(), their results get CONCATENATED, not replaced. ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+
+class InterviewState(TypedDict):
+ """State for a single WikiWriter ↔ TopicExpert conversation."""
+ messages: Annotated[list, operator.add] # Conversation history
+ analyst: dict # The Analyst persona driving this interview
+ topic: str # The research topic
+ max_turns: int # Q&A rounds (default 3)
+ turn_count: int # Current turn number
+ references: Annotated[list[str], operator.add] # URLs found during interview
+ info_snippets: Annotated[list[str], operator.add] # Collected [idx]: snippet pairs
+ summary: str # Compiled summary
+
+
+class STORMState(TypedDict):
+ """Main pipeline state flowing through all STORM phases."""
+ topic: str
+ analysts: list[dict] # Generated perspectives
+ interview_results: Annotated[list[str], operator.add] # Summaries from interviews
+ collected_info: Annotated[list[str], operator.add] # All [idx]: snippet pairs
+ collected_urls: Annotated[list[str], operator.add] # All source URLs
+ outline: str # Generated outline
+ section_texts: Annotated[list[str], operator.add] # Per-section written text
+ final_report: str # Assembled report
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ PHASE 1: DISCOVER PERSPECTIVES ║
+# ║ ║
+# ║ Reference: persona_generator.py ║
+# ║ The reference finds related Wikipedia topics, fetches their TOCs, ║
+# ║ and uses those structural outlines to generate diverse personas. ║
+# ║ We approximate this by searching for the topic and using results ║
+# ║ as context, plus always prepending a "Basic fact writer" persona. ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+
+# ── Reference prompt (GenPersona signature) ──
+PERSPECTIVE_PROMPT = """You need to select a group of Wikipedia editors who will work together \
+to create a comprehensive article on the topic. Each of them represents a different perspective, \
+role, or affiliation related to the topic. You can use other Wikipedia pages of related topics \
+for inspiration. Please list {max_perspectives} personas.
+
+Topic: {topic}
+
+Related information for context:
+{context}
+
+For each persona, provide a short summary name and a description of their expertise and angle.
+They should represent genuinely different perspectives that would ask different questions."""
+
+
+def discover_perspectives(state: STORMState) -> dict:
+ """
+ Phase 1: Generate diverse expert perspectives for the topic.
+
+ Reference approach (persona_generator.py):
+ 1. FindRelatedTopic — LLM suggests related Wikipedia pages
+ 2. Fetch TOCs from those pages — structural transfer
+ 3. GenPersona — generate personas inspired by the topic structures
+
+ We approximate this by searching for related content and using it
+ as context for persona generation. We always prepend a "Basic fact
+ writer" persona (reference does this at persona_generator.py:152).
+ """
+ import log
+
+ topic = state["topic"]
+ log.phase("Phase 1: Discover Perspectives")
+ log.step("*", "Searching for related topic context...")
+
+ # Search for related content (approximates FindRelatedTopic + TOC fetch)
+ results = tavily_client.search(topic, max_results=5, include_raw_content=False)
+ context_parts = []
+ for r in results.get("results", []):
+ title = r.get("title", "")
+ content = r.get("content", "")
+ context_parts.append(f"- {title}: {content[:200]}")
+ context = "\n".join(context_parts)
+
+ prompt = PERSPECTIVE_PROMPT.format(
+ topic=topic,
+ max_perspectives=MAX_PERSPECTIVES,
+ context=context,
+ )
+
+ log.step("*", "Generating expert perspectives (structured output)...")
+ # Manual JSON parsing — with_structured_output isn't reliably supported
+ # across all OpenRouter providers (function calling varies by backend).
+ response = llm.invoke([
+ SystemMessage(content=(
+ "Respond ONLY with valid JSON. No markdown, no explanation. "
+ 'Format: {"analysts": [{"name": "...", "description": "..."}]}'
+ )),
+ HumanMessage(content=prompt),
+ ])
+ log.track_cost(response.response_metadata)
+
+ import json
+ text = response.content.strip()
+ # Strip markdown code fences if present
+ if text.startswith("```"):
+ text = text.split("\n", 1)[1] if "\n" in text else text[3:]
+ if text.endswith("```"):
+ text = text[: text.rfind("```")]
+ perspectives = Perspectives(**json.loads(text.strip()))
+
+ # Reference always prepends a default "Basic fact writer" persona
+ default_analyst = {
+ "name": "Basic fact writer",
+ "description": "Basic fact writer focusing on broadly covering the basic facts about the topic.",
+ }
+ analysts = [default_analyst] + [a.model_dump() for a in perspectives.analysts]
+
+ log.success(f"Generated {len(analysts)} perspectives (including default fact writer):")
+ for a in analysts:
+ log.detail(f"{a['name']}: {a['description'][:80]}")
+
+ return {"analysts": analysts}
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ PHASE 2: MULTI-TURN CONVERSATIONS (WikiWriter ↔ TopicExpert) ║
+# ║ ║
+# ║ Reference: knowledge_curation.py ║
+# ║ For each persona, a ConvSimulator runs max_turn iterations: ║
+# ║ WikiWriter asks a question → TopicExpert generates queries, ║
+# ║ searches, and answers with [1],[2] citations ║
+# ║ Conversations run IN PARALLEL via Send() (ref: ThreadPoolExecutor) ║
+# ║ ║
+# ║ Key reference details: ║
+# ║ - WikiWriter uses AskQuestionWithPersona prompt ║
+# ║ - Conversation ends with "Thank you so much for your help!" ║
+# ║ - TopicExpert first generates queries (QuestionToQuery), ║
+# ║ then searches, then answers (AnswerQuestion) with inline cites ║
+# ║ - History is truncated: last 4 turns full, earlier question-only ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+# ── Reference prompts ──
+
+WIKIWRITER_PROMPT = """You are an experienced Wikipedia writer and want to edit a specific page. \
+Besides your identity as a Wikipedia writer, you have a specific focus when researching the topic.
+
+Your persona: {persona_name} — {persona_description}
+
+Now, you are chatting with an expert to get information. Ask good questions to get more useful \
+information. When you have no more questions to ask, say "Thank you so much for your help!" \
+to end the conversation.
+
+Topic: {topic}
+
+Ask only ONE focused question from your unique perspective."""
+
+QUERY_GEN_PROMPT = """You want to answer the question using Google search. \
+What do you type in the search box?
+Write the queries you will use in the following format:
+- query 1
+- query 2
+- query 3
+
+Topic: {topic}
+Question: {question}"""
+
+EXPERT_ANSWER_PROMPT = """You are an expert who can use information effectively. \
+You are chatting with a Wikipedia writer who wants to create a Wikipedia page on the topic. \
+You have gathered the following information from web searches.
+
+Make your response as informative as possible, ensuring that every sentence is supported \
+by the gathered information. Use [1], [2], etc. to reference the sources in your response.
+
+Information:
+{info}
+
+Topic: {topic}
+Question: {question}"""
+
+
+def _format_conv_history(messages: list, max_full_turns: int = 4) -> str:
+ """Format conversation history like the reference (knowledge_curation.py:103-110).
+
+ Last max_full_turns show full Q&A. Earlier turns show question only
+ with 'Omit the answer here due to space limit.'
+ """
+ pairs = []
+ for i in range(0, len(messages), 2):
+ q = messages[i].content if i < len(messages) else ""
+ a = messages[i + 1].content if i + 1 < len(messages) else ""
+ pairs.append((q, a))
+
+ total = len(pairs)
+ lines = []
+ for idx, (q, a) in enumerate(pairs):
+ lines.append(f"Wikipedia Writer: {q}")
+ if idx >= total - max_full_turns:
+ lines.append(f"Expert: {a}")
+ else:
+ lines.append("Expert: [Omit the answer here due to space limit.]")
+
+ text = "\n".join(lines)
+ # Reference truncates to 2500 words
+ words = text.split()
+ if len(words) > 2500:
+ text = " ".join(words[:2500])
+ return text
+
+
+def ask_question(state: InterviewState) -> dict:
+ """WikiWriter asks a question from the analyst's perspective.
+
+ Reference: WikiWriter.forward() in knowledge_curation.py:95-125
+ Uses AskQuestionWithPersona signature with persona + conversation history.
+ """
+ import log
+
+ analyst = state["analyst"]
+ topic = state["topic"]
+ messages = state.get("messages", [])
+ turn = state.get("turn_count", 0) + 1
+ name = analyst["name"]
+
+ log.step("?", f"[{name}] WikiWriter asking question (turn {turn}/{MAX_CONV_TURNS})")
+
+ prompt = WIKIWRITER_PROMPT.format(
+ persona_name=analyst["name"],
+ persona_description=analyst["description"],
+ topic=topic,
+ )
+
+ # Include conversation history for follow-up context
+ conv_messages = [SystemMessage(content=prompt)]
+ if messages:
+ conv_history = _format_conv_history(messages)
+ conv_messages.append(HumanMessage(
+ content=f"Conversation so far:\n{conv_history}\n\nAsk your next question."
+ ))
+
+ response = llm.invoke(conv_messages)
+ log.track_cost(response.response_metadata)
+
+ print()
+ log.conversation("WikiWriter", name, response.content)
+
+ return {
+ "messages": [HumanMessage(content=response.content, name="WikiWriter")],
+ "turn_count": turn,
+ }
+
+
+def answer_question(state: InterviewState) -> dict:
+ """TopicExpert generates queries, searches, and answers with citations.
+
+ Reference: TopicExpert.forward() in knowledge_curation.py:204-244
+ Two-step process:
+ 1. QuestionToQuery — generate search queries from the question
+ 2. Search with each query via Tavily
+ 3. AnswerQuestion — synthesize answer with [1],[2] inline citations
+ """
+ import log
+
+ topic = state["topic"]
+ analyst_name = state["analyst"]["name"]
+ messages = state.get("messages", [])
+ last_question = messages[-1].content
+
+ # ── Step 1: Generate search queries (reference: QuestionToQuery) ──
+ query_prompt = QUERY_GEN_PROMPT.format(topic=topic, question=last_question)
+ query_response = llm.invoke([HumanMessage(content=query_prompt)])
+ log.track_cost(query_response.response_metadata)
+
+ # Parse bullet-point queries and sanitize for Tavily
+ raw_queries = query_response.content.strip().split("\n")
+ queries = []
+ for line in raw_queries:
+ line = line.strip().lstrip("-").lstrip("0123456789.").strip()
+ # Strip markdown formatting and various quote characters
+ line = line.strip('"').strip("'").strip("`").strip("\u201c\u201d\u2018\u2019")
+ # Replace non-breaking hyphens and other unicode with ASCII
+ line = line.replace("\u2011", "-").replace("\u2010", "-").replace("\u2013", "-")
+ if line and len(line) > 3:
+ queries.append(line[:200])
+ queries = queries[:MAX_SEARCH_QUERIES]
+
+ if not queries:
+ queries = [f"{topic} {last_question[:50]}"]
+
+ # ── Step 2: Search with each query ──
+ all_snippets: list[str] = []
+ all_urls: list[str] = []
+ snippet_idx = len(state.get("info_snippets", [])) + 1 # Continue numbering
+
+ for query in queries:
+ log.search(query)
+ try:
+ results = tavily_client.search(query, max_results=SEARCH_TOP_K, include_raw_content=False)
+ except Exception as e:
+ log.detail(f"Search failed for query: {e}")
+ continue
+ for r in results.get("results", []):
+ url = r.get("url", "")
+ content = r.get("content", "")
+ if url and content:
+ all_snippets.append(f"[{snippet_idx}]: {content}")
+ all_urls.append(url)
+ log.detail(f"[{snippet_idx}] {url}")
+ snippet_idx += 1
+
+ # ── Step 3: Answer with citations (reference: AnswerQuestion) ──
+ # Reference limits info to 1000 words
+ info_text = "\n\n".join(all_snippets)
+ words = info_text.split()
+ if len(words) > 1000:
+ info_text = " ".join(words[:1000])
+
+ answer_prompt = EXPERT_ANSWER_PROMPT.format(
+ info=info_text if all_snippets else "No search results found.",
+ topic=topic,
+ question=last_question,
+ )
+
+ log.step("+", f"[{analyst_name}] TopicExpert synthesizing answer...")
+ response = llm.invoke([HumanMessage(content=answer_prompt)])
+ log.track_cost(response.response_metadata)
+
+ print()
+ log.conversation("TopicExpert", analyst_name, response.content)
+
+ return {
+ "messages": [AIMessage(content=response.content, name="TopicExpert")],
+ "references": all_urls,
+ "info_snippets": all_snippets,
+ }
+
+
+def compile_interview(state: InterviewState) -> dict:
+ """Compile the interview into a summary preserving citations.
+
+ Reference: After conversation completes, the full transcript is stored.
+ We compile into a structured summary for use in outline + section writing.
+ """
+ import log
+
+ messages = state.get("messages", [])
+ analyst = state["analyst"]
+ name = analyst["name"]
+
+ log.step("=", f"[{name}] Compiling interview ({len(messages)} messages)...")
+
+ conversation = "\n\n".join(
+ f"{'Wikipedia Writer' if getattr(msg, 'name', '') == 'WikiWriter' else 'Expert'}: {msg.content}"
+ for msg in messages
+ if hasattr(msg, "content") and msg.content
+ )
+
+ prompt = f"""Summarize the key findings from this research interview.
+Perspective: {analyst['name']} — {analyst['description']}
+
+Interview transcript:
+{conversation}
+
+Provide a structured summary with:
+1. Key findings (preserve all factual claims)
+2. Important data points and quotes
+3. Inline citations [1], [2] etc. as they appeared in the expert answers
+
+Keep all citations intact. Be thorough — every fact matters for article writing."""
+
+ response = llm.invoke([HumanMessage(content=prompt)])
+ log.track_cost(response.response_metadata)
+ log.success(f"[{name}] Interview compiled ({len(response.content)} chars)")
+
+ return {"summary": response.content}
+
+
+def should_continue_interview(state: InterviewState) -> Literal["answer_question", "compile_interview"]:
+ """Route: continue conversation or compile.
+
+ Reference stopping conditions (ConvSimulator.forward, line 60-67):
+ 1. Max turns reached
+ 2. WikiWriter says "Thank you so much for your help!"
+ 3. Empty utterance
+ """
+ messages = state.get("messages", [])
+ turn_count = state.get("turn_count", 0)
+
+ if turn_count >= MAX_CONV_TURNS:
+ return "compile_interview"
+
+ # Check for natural completion signal (reference: "Thank you so much for your help!")
+ if messages:
+ last = messages[-1]
+ if hasattr(last, "name") and last.name == "WikiWriter":
+ if "thank you so much" in last.content.lower():
+ return "compile_interview"
+
+ return "answer_question"
+
+
+# ── Build interview subgraph ──
+_interview_builder = StateGraph(InterviewState)
+_interview_builder.add_node("ask_question", ask_question)
+_interview_builder.add_node("answer_question", answer_question)
+_interview_builder.add_node("compile_interview", compile_interview)
+
+_interview_builder.add_edge(START, "ask_question")
+_interview_builder.add_conditional_edges(
+ "ask_question",
+ should_continue_interview,
+ ["answer_question", "compile_interview"],
+)
+_interview_builder.add_edge("answer_question", "ask_question")
+_interview_builder.add_edge("compile_interview", END)
+
+interview_graph = _interview_builder.compile()
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ FAN-OUT: Launch parallel interviews via Send() ║
+# ║ ║
+# ║ Reference: knowledge_curation.py uses ThreadPoolExecutor ║
+# ║ We use LangGraph's Send() API for the same parallel fan-out. ║
+# ║ Each Send targets conduct_interview with its own InterviewState. ║
+# ║ When all complete, interview_results are concatenated via ║
+# ║ operator.add annotation. ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+
+def initiate_interviews(state: STORMState) -> list[Send]:
+ """Fan-out: launch one interview per perspective, all in parallel."""
+ return [
+ Send(
+ "conduct_interview",
+ {
+ "messages": [],
+ "analyst": analyst,
+ "topic": state["topic"],
+ "max_turns": MAX_CONV_TURNS,
+ "turn_count": 0,
+ "references": [],
+ "info_snippets": [],
+ "summary": "",
+ },
+ )
+ for analyst in state["analysts"]
+ ]
+
+
+def conduct_interview(state: InterviewState) -> dict:
+ """Run a complete WikiWriter ↔ TopicExpert interview via the subgraph."""
+ import log
+
+ name = state["analyst"]["name"]
+ log.phase(f"Phase 2: Interview — {name}")
+ log.detail(f"Persona: {state['analyst']['description'][:80]}")
+ log.divider()
+
+ result = interview_graph.invoke(state)
+ return {
+ "interview_results": [result["summary"]],
+ "collected_info": result.get("info_snippets", []),
+ "collected_urls": result.get("references", []),
+ }
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ PHASE 3: OUTLINE GENERATION (Two-Stage) ║
+# ║ ║
+# ║ Reference: outline_generation.py ║
+# ║ Stage 1: WritePageOutline — draft from LLM knowledge ONLY ║
+# ║ Stage 2: WritePageOutlineFromConv — refine with conversation data ║
+# ║ ║
+# ║ The two-stage approach prevents the outline from being biased by ║
+# ║ whichever perspective found the most data. The LLM first proposes ║
+# ║ a structurally sound outline, then adapts it to the actual data. ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+# ── Reference prompts ──
+
+DRAFT_OUTLINE_PROMPT = """Write an outline for a Wikipedia page.
+Here is the format of your writing:
+Use "# Title" to indicate section title, "## Title" to indicate subsection title.
+Do not include other information.
+Do not include topic name itself in the outline.
+
+Topic: {topic}"""
+
+REFINE_OUTLINE_PROMPT = """Improve an outline for a Wikipedia page. \
+You already have a draft outline that covers the general information. \
+Now you want to improve it based on the information learned from an \
+information-seeking conversation to make it more informative.
+
+Topic: {topic}
+
+Draft outline:
+{old_outline}
+
+Information from expert conversations:
+{conv}
+
+Return the improved outline using "# Title" and "## Title" format.
+Do not include "References", "See also", "External links", or "Bibliography" sections."""
+
+
+def generate_outline(state: STORMState) -> dict:
+ """Phase 3: Two-stage outline generation matching the reference.
+
+ Stage 1: Draft outline from LLM parametric knowledge only
+ Stage 2: Refine with actual conversation data
+ """
+ import log
+
+ topic = state["topic"]
+ interviews = "\n\n---\n\n".join(state["interview_results"])
+
+ log.phase("Phase 3: Generate Outline (Two-Stage)")
+
+ # ── Stage 1: Draft from knowledge (reference: WritePageOutline) ──
+ log.step("*", "Stage 1: Draft outline from topic knowledge...")
+ draft_prompt = DRAFT_OUTLINE_PROMPT.format(topic=topic)
+ draft_response = llm.invoke([HumanMessage(content=draft_prompt)])
+ log.track_cost(draft_response.response_metadata)
+ log.detail(f"Draft outline: {len(draft_response.content)} chars")
+
+ # ── Stage 2: Refine with data (reference: WritePageOutlineFromConv) ──
+ log.step("*", "Stage 2: Refine outline with conversation data...")
+
+ # Reference limits conversation data to 5000 words
+ conv_words = interviews.split()
+ if len(conv_words) > 5000:
+ interviews = " ".join(conv_words[:5000])
+
+ refine_prompt = REFINE_OUTLINE_PROMPT.format(
+ topic=topic,
+ old_outline=draft_response.content,
+ conv=interviews,
+ )
+ refined_response = llm.invoke([HumanMessage(content=refine_prompt)])
+ log.track_cost(refined_response.response_metadata)
+
+ log.success(f"Outline refined ({len(refined_response.content)} chars)")
+ for line in refined_response.content.strip().split("\n")[:8]:
+ if line.strip():
+ log.detail(line.strip())
+
+ return {"outline": refined_response.content}
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ PHASE 4: PER-SECTION ARTICLE WRITING ║
+# ║ ║
+# ║ Reference: article_generation.py ║
+# ║ Each top-level section is written independently with relevant ║
+# ║ information retrieved from the collected snippets. ║
+# ║ Reference uses SentenceTransformer cosine similarity for retrieval. ║
+# ║ We pass all collected info (small enough for a demo query). ║
+# ║ ║
+# ║ Key: sections are written IN PARALLEL (ref: ThreadPoolExecutor). ║
+# ║ We write them sequentially for clearer demo logging. ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+# ── Reference prompt (WriteSection signature) ──
+
+WRITE_SECTION_PROMPT = """Write a Wikipedia section based on the collected information.
+Here is the format of your writing:
+1. Use "# Title" to indicate section title, "## Title" to indicate subsection title.
+2. Use [1], [2], ..., [n] in line (for example, "The capital of the United States is Washington, D.C.[1][3]."). \
+You DO NOT need to include a References or Sources section.
+
+Topic: {topic}
+Section to write: {section}
+Section outline: {section_outline}
+
+Collected information:
+{info}
+
+Start your writing with # {section}. Don't include the page title or try to write other sections."""
+
+
+def write_sections(state: STORMState) -> dict:
+ """Phase 4a: Write each top-level section independently.
+
+ Reference: article_generation.py:53-133
+ Parses the outline into sections, writes each one with relevant info.
+ Skips "introduction", "conclusion", "summary" sections.
+ """
+ import log
+
+ topic = state["topic"]
+ outline = state["outline"]
+ interviews = "\n\n---\n\n".join(state["interview_results"])
+
+ log.phase("Phase 4: Write Article (Per-Section)")
+
+ # Parse top-level sections from outline
+ sections: list[tuple[str, str]] = [] # (section_name, section_outline)
+ current_section = ""
+ current_content: list[str] = []
+
+ for line in outline.strip().split("\n"):
+ stripped = line.strip()
+ if stripped.startswith("# ") and not stripped.startswith("## "):
+ if current_section:
+ sections.append((current_section, "\n".join(current_content)))
+ current_section = stripped.lstrip("# ").strip()
+ current_content = [stripped]
+ elif current_section:
+ current_content.append(stripped)
+
+ if current_section:
+ sections.append((current_section, "\n".join(current_content)))
+
+ # Filter out intro/conclusion/summary (reference: article_generation.py:97-103)
+ skip_names = {"introduction", "conclusion", "summary", "references", "see also", "external links"}
+ sections = [(name, outline_text) for name, outline_text in sections
+ if name.lower() not in skip_names]
+
+ log.step("*", f"Writing {len(sections)} sections...")
+
+ # Use all collected info as context (reference uses cosine similarity retrieval)
+ info_text = "\n\n".join(state.get("collected_info", []))
+ if not info_text:
+ info_text = interviews # Use interview summaries as context
+
+ # Limit info to prevent context overflow
+ words = info_text.split()
+ if len(words) > 3000:
+ info_text = " ".join(words[:3000])
+
+ section_texts: list[str] = []
+ for section_name, section_outline in sections:
+ log.step(">", f"Writing: {section_name}")
+
+ prompt = WRITE_SECTION_PROMPT.format(
+ topic=topic,
+ section=section_name,
+ section_outline=section_outline,
+ info=info_text,
+ )
+
+ response = llm.invoke([HumanMessage(content=prompt)])
+ log.track_cost(response.response_metadata)
+ log.detail(f"{len(response.content)} chars")
+ section_texts.append(response.content)
+
+ log.success(f"Wrote {len(section_texts)} sections")
+ return {"section_texts": section_texts}
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ PHASE 5: LEAD SECTION + ASSEMBLY ║
+# ║ ║
+# ║ Reference: article_polish.py ║
+# ║ Lead section is written AFTER the body so it reflects actual ║
+# ║ content. Optional dedup pass removes repeated information. ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+# ── Reference prompt (WriteLeadSection signature) ──
+
+LEAD_SECTION_PROMPT = """Write a lead section for the given Wikipedia page with the following guidelines:
+1. The lead should stand on its own as a concise overview of the article's topic.
+2. The lead section should be concise and contain no more than four well-composed paragraphs.
+3. The lead section should be carefully sourced as appropriate. Add inline citations [1], [2], etc.
+4. The lead section should not contain any headings.
+
+Topic: {topic}
+
+Full article:
+{article}
+
+Write only the lead section (no heading needed)."""
+
+
+def write_lead_and_assemble(state: STORMState) -> dict:
+ """Phase 5: Write lead section and assemble the final article.
+
+ Reference: article_polish.py:29-53
+ 1. Write lead section based on full article body
+ 2. Prepend lead as "# Summary"
+ 3. Build a unified references section from collected URLs
+ """
+ import log
+
+ topic = state["topic"]
+ section_texts = state.get("section_texts", [])
+ collected_urls = state.get("collected_urls", [])
+
+ log.phase("Phase 5: Lead Section + Assembly")
+
+ # Assemble the body from per-section texts
+ body = "\n\n".join(section_texts)
+
+ # ── Write lead section (reference: WriteLeadSection) ──
+ log.step("*", "Writing lead section...")
+ lead_prompt = LEAD_SECTION_PROMPT.format(topic=topic, article=body)
+ lead_response = llm.invoke([HumanMessage(content=lead_prompt)])
+ log.track_cost(lead_response.response_metadata)
+ log.detail(f"Lead section: {len(lead_response.content)} chars")
+
+ # ── Build references section from collected URLs ──
+ unique_urls = list(dict.fromkeys(collected_urls)) # Deduplicate, preserve order
+ references_section = "\n\n## References\n\n"
+ for i, url in enumerate(unique_urls, 1):
+ references_section += f"[{i}] {url}\n"
+
+ # ── Assemble final article ──
+ final_report = f"# {topic}\n\n{lead_response.content}\n\n{body}{references_section}"
+
+ log.success(f"Final article assembled ({len(final_report)} chars, {len(unique_urls)} sources)")
+ return {"final_report": final_report}
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ GRAPH ASSEMBLY ║
+# ║ ║
+# ║ The STORM pipeline is LINEAR — each phase feeds the next. ║
+# ║ Parallelism happens WITHIN Phase 2 via Send() fan-out. ║
+# ║ ║
+# ║ Reference pipeline: ║
+# ║ knowledge_curation → outline_generation → article_generation ║
+# ║ → article_polishing ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+builder = StateGraph(STORMState)
+
+builder.add_node("discover_perspectives", discover_perspectives)
+builder.add_node("conduct_interview", conduct_interview)
+builder.add_node("generate_outline", generate_outline)
+builder.add_node("write_sections", write_sections)
+builder.add_node("write_lead_and_assemble", write_lead_and_assemble)
+
+# Wire the pipeline
+builder.add_edge(START, "discover_perspectives")
+builder.add_conditional_edges("discover_perspectives", initiate_interviews, ["conduct_interview"])
+builder.add_edge("conduct_interview", "generate_outline")
+builder.add_edge("generate_outline", "write_sections")
+builder.add_edge("write_sections", "write_lead_and_assemble")
+builder.add_edge("write_lead_and_assemble", END)
+
+graph = builder.compile()
+
+
+# ╔══════════════════════════════════════════════════════════════════════╗
+# ║ ENTRY POINT HELPER ║
+# ╚══════════════════════════════════════════════════════════════════════╝
+
+
+def initial_state(query: str) -> STORMState:
+ """Build the starting state for the STORM agent."""
+ return {
+ "topic": query,
+ "analysts": [],
+ "interview_results": [],
+ "collected_info": [],
+ "collected_urls": [],
+ "outline": "",
+ "section_texts": [],
+ "final_report": "",
+ }
diff --git a/presentations/deep-research/demos/test_agents.py b/presentations/deep-research/demos/test_agents.py
new file mode 100644
index 0000000..3d22a9d
--- /dev/null
+++ b/presentations/deep-research/demos/test_agents.py
@@ -0,0 +1,403 @@
+"""
+Unit tests for Deep Research demo agents.
+
+Tests graph structure, state handling, and routing logic WITHOUT making
+real LLM/search API calls. Each agent's compiled graph is tested for:
+- Correct node wiring (edges)
+- State initialization
+- Routing/conditional edge logic
+"""
+
+import operator
+from typing import Annotated
+from unittest.mock import MagicMock, patch
+
+import pytest
+from langchain_core.messages import AIMessage, HumanMessage, ToolMessage
+from typing_extensions import TypedDict
+
+
+# ── Helpers ──────────────────────────────────────────────────────────────
+
+# Set dummy env vars before importing agents (they create LLM at import time)
+import os
+
+os.environ.setdefault("OPENROUTER_API_KEY", "test-key")
+os.environ.setdefault("TAVILY_API_KEY", "test-key")
+
+
+# ═══════════════════════════════════════════════════════════════════════════
+# ReAct Agent Tests
+# ═══════════════════════════════════════════════════════════════════════════
+
+
+class TestReActAgent:
+ """Tests for the ReAct (Think-Act-Observe) agent."""
+
+ def test_graph_has_expected_nodes(self):
+ from react_agent import graph
+
+ node_names = set(graph.nodes.keys())
+ # LangGraph adds __start__ and __end__ pseudo-nodes
+ assert "agent" in node_names
+ assert "tools" in node_names
+
+ def test_initial_state_has_human_message(self):
+ from react_agent import initial_state
+
+ state = initial_state("test query")
+ assert len(state["messages"]) == 1
+ assert isinstance(state["messages"][0], HumanMessage)
+ assert state["messages"][0].content == "test query"
+
+ def test_should_continue_routes_to_tools_on_tool_calls(self):
+ from react_agent import should_continue
+
+ # Create a mock AI message WITH tool calls
+ msg = AIMessage(content="", tool_calls=[{"id": "1", "name": "search", "args": {"query": "test"}}])
+ state = {"messages": [msg]}
+
+ result = should_continue(state)
+ assert result == "tools"
+
+ def test_should_continue_routes_to_end_on_no_tool_calls(self):
+ from react_agent import should_continue
+
+ # Create a mock AI message WITHOUT tool calls
+ msg = AIMessage(content="Here is the answer.")
+ state = {"messages": [msg]}
+
+ result = should_continue(state)
+ assert result == "__end__"
+
+ def test_graph_compiles(self):
+ """The graph should compile without errors."""
+ from react_agent import graph
+
+ assert graph is not None
+ # Should be invocable (has invoke method)
+ assert hasattr(graph, "invoke")
+ assert hasattr(graph, "stream")
+
+
+# ═══════════════════════════════════════════════════════════════════════════
+# STORM Agent Tests
+# ═══════════════════════════════════════════════════════════════════════════
+
+
+class TestSTORMAgent:
+ """Tests for the STORM (Multi-Perspective Research) agent."""
+
+ def test_graph_has_expected_nodes(self):
+ from storm_agent import graph
+
+ node_names = set(graph.nodes.keys())
+ assert "discover_perspectives" in node_names
+ assert "conduct_interview" in node_names
+ assert "generate_outline" in node_names
+ assert "write_report" in node_names
+
+ def test_initial_state_structure(self):
+ from storm_agent import initial_state
+
+ state = initial_state("test topic")
+ assert state["topic"] == "test topic"
+ assert state["analysts"] == []
+ assert state["interview_results"] == []
+ assert state["outline"] == ""
+ assert state["final_report"] == ""
+
+ def test_interview_subgraph_has_expected_nodes(self):
+ from storm_agent import interview_graph
+
+ node_names = set(interview_graph.nodes.keys())
+ assert "ask_question" in node_names
+ assert "answer_question" in node_names
+ assert "compile_interview" in node_names
+
+ def test_should_continue_interview_respects_max_turns(self):
+ from storm_agent import should_continue_interview
+
+ # 3 turns = 6 messages (Q&A pairs)
+ messages = [
+ HumanMessage(content="q1", name="WikiWriter"),
+ AIMessage(content="a1", name="TopicExpert"),
+ HumanMessage(content="q2", name="WikiWriter"),
+ AIMessage(content="a2", name="TopicExpert"),
+ HumanMessage(content="q3", name="WikiWriter"),
+ AIMessage(content="a3", name="TopicExpert"),
+ ]
+ state = {"messages": messages, "max_turns": 3}
+
+ result = should_continue_interview(state)
+ assert result == "compile_interview"
+
+ def test_should_continue_interview_continues_when_turns_remain(self):
+ from storm_agent import should_continue_interview
+
+ messages = [
+ HumanMessage(content="q1", name="WikiWriter"),
+ AIMessage(content="a1", name="TopicExpert"),
+ ]
+ state = {"messages": messages, "max_turns": 3}
+
+ result = should_continue_interview(state)
+ assert result == "answer_question"
+
+ def test_should_continue_interview_stops_on_complete_signal(self):
+ from storm_agent import should_continue_interview
+
+ messages = [
+ HumanMessage(content="INTERVIEW_COMPLETE", name="WikiWriter"),
+ ]
+ state = {"messages": messages, "max_turns": 5}
+
+ result = should_continue_interview(state)
+ assert result == "compile_interview"
+
+ def test_initiate_interviews_creates_sends(self):
+ from storm_agent import initiate_interviews
+ from langgraph.types import Send
+
+ state = {
+ "topic": "AI safety",
+ "analysts": [
+ {"name": "Alice", "role": "Engineer", "focus": "technical", "description": "..."},
+ {"name": "Bob", "role": "Ethicist", "focus": "ethics", "description": "..."},
+ ],
+ "interview_results": [],
+ "outline": "",
+ "final_report": "",
+ }
+
+ sends = initiate_interviews(state)
+ assert len(sends) == 2
+ assert all(isinstance(s, Send) for s in sends)
+
+ def test_analyst_pydantic_model(self):
+ from storm_agent import Analyst
+
+ analyst = Analyst(
+ name="Test",
+ role="Engineer",
+ focus="technical details",
+ description="A test analyst",
+ )
+ assert analyst.name == "Test"
+ dumped = analyst.model_dump()
+ assert "name" in dumped
+ assert "role" in dumped
+
+ def test_graph_compiles(self):
+ from storm_agent import graph
+
+ assert graph is not None
+ assert hasattr(graph, "invoke")
+ assert hasattr(graph, "stream")
+
+
+# ═══════════════════════════════════════════════════════════════════════════
+# Diffusion Agent Tests
+# ═══════════════════════════════════════════════════════════════════════════
+
+
+class TestDiffusionAgent:
+ """Tests for the Diffusion (Iterative Refinement) agent."""
+
+ def test_graph_has_expected_nodes(self):
+ from diffusion_agent import graph
+
+ node_names = set(graph.nodes.keys())
+ assert "generate_brief" in node_names
+ assert "generate_noisy_draft" in node_names
+ assert "identify_gaps" in node_names
+ assert "research_sub_agent" in node_names
+ assert "refine_draft" in node_names
+ assert "generate_report" in node_names
+
+ def test_initial_state_structure(self):
+ from diffusion_agent import initial_state
+
+ state = initial_state("test query")
+ assert state["query"] == "test query"
+ assert state["research_brief"] == ""
+ assert state["current_draft"] == ""
+ assert state["iteration"] == 0
+ assert state["max_iterations"] == 3
+ assert state["research_findings"] == []
+ assert state["sources"] == []
+ assert state["research_questions"] == []
+ assert state["final_report"] == ""
+
+ def test_should_continue_stops_at_max_iterations(self):
+ from diffusion_agent import should_continue
+
+ state = {
+ "query": "test",
+ "current_draft": "Some draft content.",
+ "iteration": 3,
+ "max_iterations": 3,
+ }
+
+ result = should_continue(state)
+ assert result == "generate_report"
+
+ def test_dispatch_research_creates_sends(self):
+ from diffusion_agent import dispatch_research
+ from langgraph.types import Send
+
+ state = {
+ "query": "AI safety",
+ "research_questions": ["What is alignment?", "What are risks?"],
+ "research_brief": "",
+ "current_draft": "",
+ "iteration": 0,
+ "max_iterations": 3,
+ "research_findings": [],
+ "sources": [],
+ "final_report": "",
+ }
+
+ sends = dispatch_research(state)
+ assert len(sends) == 2
+ assert all(isinstance(s, Send) for s in sends)
+
+ def test_state_iteration_uses_operator_add(self):
+ """Verify that iteration field uses operator.add annotation."""
+ from diffusion_agent import DiffusionState
+
+ annotations = DiffusionState.__annotations__
+ # Check that iteration is Annotated with operator.add
+ import typing
+ hint = typing.get_type_hints(DiffusionState, include_extras=True)
+ iter_hint = hint["iteration"]
+ # Annotated types have __metadata__
+ assert hasattr(iter_hint, "__metadata__")
+ assert operator.add in iter_hint.__metadata__
+
+ def test_state_research_findings_uses_operator_add(self):
+ """Verify that research_findings uses operator.add for safe parallel merging."""
+ from diffusion_agent import DiffusionState
+
+ import typing
+ hint = typing.get_type_hints(DiffusionState, include_extras=True)
+ findings_hint = hint["research_findings"]
+ assert hasattr(findings_hint, "__metadata__")
+ assert operator.add in findings_hint.__metadata__
+
+ def test_graph_compiles(self):
+ from diffusion_agent import graph
+
+ assert graph is not None
+ assert hasattr(graph, "invoke")
+ assert hasattr(graph, "stream")
+
+
+# ═══════════════════════════════════════════════════════════════════════════
+# Log Module Tests
+# ═══════════════════════════════════════════════════════════════════════════
+
+
+class TestLogModule:
+ """Tests for the shared logging helpers."""
+
+ def test_cost_tracking_accumulates(self):
+ import log
+
+ log.reset_cost()
+
+ log.track_cost({"token_usage": {"prompt_tokens": 100, "completion_tokens": 50, "cost": 0.001}})
+ log.track_cost({"token_usage": {"prompt_tokens": 200, "completion_tokens": 100, "cost": 0.002}})
+
+ total_cost, total_calls = log.get_total_cost()
+ assert total_calls == 2
+ assert abs(total_cost - 0.003) < 1e-9
+
+ def test_cost_tracking_reset(self):
+ import log
+
+ log.track_cost({"token_usage": {"cost": 0.005}})
+ log.reset_cost()
+
+ total_cost, total_calls = log.get_total_cost()
+ assert total_cost == 0.0
+ assert total_calls == 0
+
+ def test_cost_tracking_handles_missing_fields(self):
+ import log
+
+ log.reset_cost()
+ # Empty metadata should not crash
+ log.track_cost({})
+ log.track_cost({"token_usage": {}})
+ log.track_cost({"token_usage": None})
+
+ total_cost, total_calls = log.get_total_cost()
+ assert total_calls == 3
+ assert total_cost == 0.0
+
+
+# ═══════════════════════════════════════════════════════════════════════════
+# Integration Tests (require real API keys)
+# ═══════════════════════════════════════════════════════════════════════════
+
+
+@pytest.mark.skipif(
+ os.environ.get("OPENROUTER_API_KEY", "test-key") == "test-key",
+ reason="Requires real OPENROUTER_API_KEY",
+)
+class TestCostTrackingIntegration:
+ """Integration tests that make real LLM calls to verify cost tracking."""
+
+ def test_response_metadata_structure(self):
+ """Dump response_metadata to discover where OpenRouter puts cost info."""
+ import json
+
+ from langchain_openai import ChatOpenAI
+ from langchain_core.messages import HumanMessage
+
+ llm = ChatOpenAI(
+ model="openai/gpt-oss-120b",
+ base_url="https://openrouter.ai/api/v1",
+ api_key=os.environ["OPENROUTER_API_KEY"],
+ temperature=0,
+ extra_body={"provider": {"order": ["Groq"]}},
+ )
+
+ response = llm.invoke([HumanMessage(content="Say hi in one word.")])
+
+ metadata = response.response_metadata
+ print("\n=== Full response_metadata ===")
+ print(json.dumps(metadata, indent=2, default=str))
+
+ if hasattr(response, "usage_metadata") and response.usage_metadata:
+ print("\n=== usage_metadata ===")
+ um = response.usage_metadata
+ print(json.dumps(
+ um if isinstance(um, dict) else (vars(um) if hasattr(um, "__dict__") else str(um)),
+ indent=2,
+ default=str,
+ ))
+
+ # This test always passes — it's for inspection
+ assert response.content # got a response
+
+ def test_react_agent_tracks_cost(self):
+ """Run a real ReAct call and verify cost > 0."""
+ import log
+
+ log.reset_cost()
+
+ from react_agent import graph, initial_state
+
+ state = initial_state("What is 2+2? Answer in one word.")
+ config = {"recursion_limit": 10}
+
+ final_state = state
+ for update in graph.stream(state, config=config, stream_mode="values"):
+ final_state = update
+
+ total_cost, total_calls = log.get_total_cost()
+ print(f"\nTotal cost: ${total_cost:.6f}, calls: {total_calls}")
+ assert total_calls > 0, "Expected at least one LLM call"
+ assert total_cost > 0.0, f"Expected cost > 0, got ${total_cost:.6f}"
diff --git a/presentations/deep-research/demos/uv.lock b/presentations/deep-research/demos/uv.lock
new file mode 100644
index 0000000..b1a8e5b
--- /dev/null
+++ b/presentations/deep-research/demos/uv.lock
@@ -0,0 +1,1836 @@
+version = 1
+revision = 3
+requires-python = ">=3.11"
+resolution-markers = [
+ "python_full_version >= '3.13'",
+ "python_full_version < '3.13'",
+]
+
+[[package]]
+name = "aiohappyeyeballs"
+version = "2.6.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/26/30/f84a107a9c4331c14b2b586036f40965c128aa4fee4dda5d3d51cb14ad54/aiohappyeyeballs-2.6.1.tar.gz", hash = "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558", size = 22760, upload-time = "2025-03-12T01:42:48.764Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8", size = 15265, upload-time = "2025-03-12T01:42:47.083Z" },
+]
+
+[[package]]
+name = "aiohttp"
+version = "3.13.3"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "aiohappyeyeballs" },
+ { name = "aiosignal" },
+ { name = "attrs" },
+ { name = "frozenlist" },
+ { name = "multidict" },
+ { name = "propcache" },
+ { name = "yarl" },
+]
+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/f1/4c/a164164834f03924d9a29dc3acd9e7ee58f95857e0b467f6d04298594ebb/aiohttp-3.13.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5b6073099fb654e0a068ae678b10feff95c5cae95bbfcbfa7af669d361a8aa6b", size = 746051, upload-time = "2026-01-03T17:29:43.287Z" },
+ { url = "https://files.pythonhosted.org/packages/82/71/d5c31390d18d4f58115037c432b7e0348c60f6f53b727cad33172144a112/aiohttp-3.13.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cb93e166e6c28716c8c6aeb5f99dfb6d5ccf482d29fe9bf9a794110e6d0ab64", size = 499234, upload-time = "2026-01-03T17:29:44.822Z" },
+ { url = "https://files.pythonhosted.org/packages/0e/c9/741f8ac91e14b1d2e7100690425a5b2b919a87a5075406582991fb7de920/aiohttp-3.13.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:28e027cf2f6b641693a09f631759b4d9ce9165099d2b5d92af9bd4e197690eea", size = 494979, upload-time = "2026-01-03T17:29:46.405Z" },
+ { url = "https://files.pythonhosted.org/packages/75/b5/31d4d2e802dfd59f74ed47eba48869c1c21552c586d5e81a9d0d5c2ad640/aiohttp-3.13.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3b61b7169ababd7802f9568ed96142616a9118dd2be0d1866e920e77ec8fa92a", size = 1748297, upload-time = "2026-01-03T17:29:48.083Z" },
+ { url = "https://files.pythonhosted.org/packages/1a/3e/eefad0ad42959f226bb79664826883f2687d602a9ae2941a18e0484a74d3/aiohttp-3.13.3-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:80dd4c21b0f6237676449c6baaa1039abae86b91636b6c91a7f8e61c87f89540", size = 1707172, upload-time = "2026-01-03T17:29:49.648Z" },
+ { url = "https://files.pythonhosted.org/packages/c5/3a/54a64299fac2891c346cdcf2aa6803f994a2e4beeaf2e5a09dcc54acc842/aiohttp-3.13.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:65d2ccb7eabee90ce0503c17716fc77226be026dcc3e65cce859a30db715025b", size = 1805405, upload-time = "2026-01-03T17:29:51.244Z" },
+ { url = "https://files.pythonhosted.org/packages/6c/70/ddc1b7169cf64075e864f64595a14b147a895a868394a48f6a8031979038/aiohttp-3.13.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5b179331a481cb5529fca8b432d8d3c7001cb217513c94cd72d668d1248688a3", size = 1899449, upload-time = "2026-01-03T17:29:53.938Z" },
+ { url = "https://files.pythonhosted.org/packages/a1/7e/6815aab7d3a56610891c76ef79095677b8b5be6646aaf00f69b221765021/aiohttp-3.13.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d4c940f02f49483b18b079d1c27ab948721852b281f8b015c058100e9421dd1", size = 1748444, upload-time = "2026-01-03T17:29:55.484Z" },
+ { url = "https://files.pythonhosted.org/packages/6b/f2/073b145c4100da5511f457dc0f7558e99b2987cf72600d42b559db856fbc/aiohttp-3.13.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f9444f105664c4ce47a2a7171a2418bce5b7bae45fb610f4e2c36045d85911d3", size = 1606038, upload-time = "2026-01-03T17:29:57.179Z" },
+ { url = "https://files.pythonhosted.org/packages/0a/c1/778d011920cae03ae01424ec202c513dc69243cf2db303965615b81deeea/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:694976222c711d1d00ba131904beb60534f93966562f64440d0c9d41b8cdb440", size = 1724156, upload-time = "2026-01-03T17:29:58.914Z" },
+ { url = "https://files.pythonhosted.org/packages/0e/cb/3419eabf4ec1e9ec6f242c32b689248365a1cf621891f6f0386632525494/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f33ed1a2bf1997a36661874b017f5c4b760f41266341af36febaf271d179f6d7", size = 1722340, upload-time = "2026-01-03T17:30:01.962Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/e5/76cf77bdbc435bf233c1f114edad39ed4177ccbfab7c329482b179cff4f4/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e636b3c5f61da31a92bf0d91da83e58fdfa96f178ba682f11d24f31944cdd28c", size = 1783041, upload-time = "2026-01-03T17:30:03.609Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/d4/dd1ca234c794fd29c057ce8c0566b8ef7fd6a51069de5f06fa84b9a1971c/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:5d2d94f1f5fcbe40838ac51a6ab5704a6f9ea42e72ceda48de5e6b898521da51", size = 1596024, upload-time = "2026-01-03T17:30:05.132Z" },
+ { url = "https://files.pythonhosted.org/packages/55/58/4345b5f26661a6180afa686c473620c30a66afdf120ed3dd545bbc809e85/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2be0e9ccf23e8a94f6f0650ce06042cefc6ac703d0d7ab6c7a917289f2539ad4", size = 1804590, upload-time = "2026-01-03T17:30:07.135Z" },
+ { url = "https://files.pythonhosted.org/packages/7b/06/05950619af6c2df7e0a431d889ba2813c9f0129cec76f663e547a5ad56f2/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9af5e68ee47d6534d36791bbe9b646d2a7c7deb6fc24d7943628edfbb3581f29", size = 1740355, upload-time = "2026-01-03T17:30:09.083Z" },
+ { url = "https://files.pythonhosted.org/packages/3e/80/958f16de79ba0422d7c1e284b2abd0c84bc03394fbe631d0a39ffa10e1eb/aiohttp-3.13.3-cp311-cp311-win32.whl", hash = "sha256:a2212ad43c0833a873d0fb3c63fa1bacedd4cf6af2fee62bf4b739ceec3ab239", size = 433701, upload-time = "2026-01-03T17:30:10.869Z" },
+ { url = "https://files.pythonhosted.org/packages/dc/f2/27cdf04c9851712d6c1b99df6821a6623c3c9e55956d4b1e318c337b5a48/aiohttp-3.13.3-cp311-cp311-win_amd64.whl", hash = "sha256:642f752c3eb117b105acbd87e2c143de710987e09860d674e068c4c2c441034f", size = 457678, upload-time = "2026-01-03T17:30:12.719Z" },
+ { 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" },
+ { url = "https://files.pythonhosted.org/packages/54/d4/438efabdf74e30aeceb890c3290bbaa449780583b1270b00661126b8aae4/aiohttp-3.13.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:48e377758516d262bde50c2584fc6c578af272559c409eecbdd2bae1601184d6", size = 1717263, upload-time = "2026-01-03T17:31:23.296Z" },
+ { url = "https://files.pythonhosted.org/packages/71/f2/7bddc7fd612367d1459c5bcf598a9e8f7092d6580d98de0e057eb42697ad/aiohttp-3.13.3-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:34749271508078b261c4abb1767d42b8d0c0cc9449c73a4df494777dc55f0687", size = 1669107, upload-time = "2026-01-03T17:31:25.334Z" },
+ { url = "https://files.pythonhosted.org/packages/00/5a/1aeaecca40e22560f97610a329e0e5efef5e0b5afdf9f857f0d93839ab2e/aiohttp-3.13.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:82611aeec80eb144416956ec85b6ca45a64d76429c1ed46ae1b5f86c6e0c9a26", size = 1760196, upload-time = "2026-01-03T17:31:27.394Z" },
+ { url = "https://files.pythonhosted.org/packages/f8/f8/0ff6992bea7bd560fc510ea1c815f87eedd745fe035589c71ce05612a19a/aiohttp-3.13.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2fff83cfc93f18f215896e3a190e8e5cb413ce01553901aca925176e7568963a", size = 1843591, upload-time = "2026-01-03T17:31:29.238Z" },
+ { url = "https://files.pythonhosted.org/packages/e3/d1/e30e537a15f53485b61f5be525f2157da719819e8377298502aebac45536/aiohttp-3.13.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bbe7d4cecacb439e2e2a8a1a7b935c25b812af7a5fd26503a66dadf428e79ec1", size = 1720277, upload-time = "2026-01-03T17:31:31.053Z" },
+ { url = "https://files.pythonhosted.org/packages/84/45/23f4c451d8192f553d38d838831ebbc156907ea6e05557f39563101b7717/aiohttp-3.13.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b928f30fe49574253644b1ca44b1b8adbd903aa0da4b9054a6c20fc7f4092a25", size = 1548575, upload-time = "2026-01-03T17:31:32.87Z" },
+ { url = "https://files.pythonhosted.org/packages/6a/ed/0a42b127a43712eda7807e7892c083eadfaf8429ca8fb619662a530a3aab/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7b5e8fe4de30df199155baaf64f2fcd604f4c678ed20910db8e2c66dc4b11603", size = 1679455, upload-time = "2026-01-03T17:31:34.76Z" },
+ { url = "https://files.pythonhosted.org/packages/2e/b5/c05f0c2b4b4fe2c9d55e73b6d3ed4fd6c9dc2684b1d81cbdf77e7fad9adb/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:8542f41a62bcc58fc7f11cf7c90e0ec324ce44950003feb70640fc2a9092c32a", size = 1687417, upload-time = "2026-01-03T17:31:36.699Z" },
+ { url = "https://files.pythonhosted.org/packages/c9/6b/915bc5dad66aef602b9e459b5a973529304d4e89ca86999d9d75d80cbd0b/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:5e1d8c8b8f1d91cd08d8f4a3c2b067bfca6ec043d3ff36de0f3a715feeedf926", size = 1729968, upload-time = "2026-01-03T17:31:38.622Z" },
+ { url = "https://files.pythonhosted.org/packages/11/3b/e84581290a9520024a08640b63d07673057aec5ca548177a82026187ba73/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:90455115e5da1c3c51ab619ac57f877da8fd6d73c05aacd125c5ae9819582aba", size = 1545690, upload-time = "2026-01-03T17:31:40.57Z" },
+ { url = "https://files.pythonhosted.org/packages/f5/04/0c3655a566c43fd647c81b895dfe361b9f9ad6d58c19309d45cff52d6c3b/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:042e9e0bcb5fba81886c8b4fbb9a09d6b8a00245fd8d88e4d989c1f96c74164c", size = 1746390, upload-time = "2026-01-03T17:31:42.857Z" },
+ { url = "https://files.pythonhosted.org/packages/1f/53/71165b26978f719c3419381514c9690bd5980e764a09440a10bb816ea4ab/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2eb752b102b12a76ca02dff751a801f028b4ffbbc478840b473597fc91a9ed43", size = 1702188, upload-time = "2026-01-03T17:31:44.984Z" },
+ { url = "https://files.pythonhosted.org/packages/29/a7/cbe6c9e8e136314fa1980da388a59d2f35f35395948a08b6747baebb6aa6/aiohttp-3.13.3-cp314-cp314-win32.whl", hash = "sha256:b556c85915d8efaed322bf1bdae9486aa0f3f764195a0fb6ee962e5c71ef5ce1", size = 433126, upload-time = "2026-01-03T17:31:47.463Z" },
+ { url = "https://files.pythonhosted.org/packages/de/56/982704adea7d3b16614fc5936014e9af85c0e34b58f9046655817f04306e/aiohttp-3.13.3-cp314-cp314-win_amd64.whl", hash = "sha256:9bf9f7a65e7aa20dd764151fb3d616c81088f91f8df39c3893a536e279b4b984", size = 459128, upload-time = "2026-01-03T17:31:49.2Z" },
+ { url = "https://files.pythonhosted.org/packages/6c/2a/3c79b638a9c3d4658d345339d22070241ea341ed4e07b5ac60fb0f418003/aiohttp-3.13.3-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:05861afbbec40650d8a07ea324367cb93e9e8cc7762e04dd4405df99fa65159c", size = 769512, upload-time = "2026-01-03T17:31:51.134Z" },
+ { url = "https://files.pythonhosted.org/packages/29/b9/3e5014d46c0ab0db8707e0ac2711ed28c4da0218c358a4e7c17bae0d8722/aiohttp-3.13.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2fc82186fadc4a8316768d61f3722c230e2c1dcab4200d52d2ebdf2482e47592", size = 506444, upload-time = "2026-01-03T17:31:52.85Z" },
+ { url = "https://files.pythonhosted.org/packages/90/03/c1d4ef9a054e151cd7839cdc497f2638f00b93cbe8043983986630d7a80c/aiohttp-3.13.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0add0900ff220d1d5c5ebbf99ed88b0c1bbf87aa7e4262300ed1376a6b13414f", size = 510798, upload-time = "2026-01-03T17:31:54.91Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/76/8c1e5abbfe8e127c893fe7ead569148a4d5a799f7cf958d8c09f3eedf097/aiohttp-3.13.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:568f416a4072fbfae453dcf9a99194bbb8bdeab718e08ee13dfa2ba0e4bebf29", size = 1868835, upload-time = "2026-01-03T17:31:56.733Z" },
+ { url = "https://files.pythonhosted.org/packages/8e/ac/984c5a6f74c363b01ff97adc96a3976d9c98940b8969a1881575b279ac5d/aiohttp-3.13.3-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:add1da70de90a2569c5e15249ff76a631ccacfe198375eead4aadf3b8dc849dc", size = 1720486, upload-time = "2026-01-03T17:31:58.65Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/9a/b7039c5f099c4eb632138728828b33428585031a1e658d693d41d07d89d1/aiohttp-3.13.3-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:10b47b7ba335d2e9b1239fa571131a87e2d8ec96b333e68b2a305e7a98b0bae2", size = 1847951, upload-time = "2026-01-03T17:32:00.989Z" },
+ { url = "https://files.pythonhosted.org/packages/3c/02/3bec2b9a1ba3c19ff89a43a19324202b8eb187ca1e928d8bdac9bbdddebd/aiohttp-3.13.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3dd4dce1c718e38081c8f35f323209d4c1df7d4db4bab1b5c88a6b4d12b74587", size = 1941001, upload-time = "2026-01-03T17:32:03.122Z" },
+ { url = "https://files.pythonhosted.org/packages/37/df/d879401cedeef27ac4717f6426c8c36c3091c6e9f08a9178cc87549c537f/aiohttp-3.13.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34bac00a67a812570d4a460447e1e9e06fae622946955f939051e7cc895cfab8", size = 1797246, upload-time = "2026-01-03T17:32:05.255Z" },
+ { url = "https://files.pythonhosted.org/packages/8d/15/be122de1f67e6953add23335c8ece6d314ab67c8bebb3f181063010795a7/aiohttp-3.13.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a19884d2ee70b06d9204b2727a7b9f983d0c684c650254679e716b0b77920632", size = 1627131, upload-time = "2026-01-03T17:32:07.607Z" },
+ { url = "https://files.pythonhosted.org/packages/12/12/70eedcac9134cfa3219ab7af31ea56bc877395b1ac30d65b1bc4b27d0438/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5f8ca7f2bb6ba8348a3614c7918cc4bb73268c5ac2a207576b7afea19d3d9f64", size = 1795196, upload-time = "2026-01-03T17:32:09.59Z" },
+ { url = "https://files.pythonhosted.org/packages/32/11/b30e1b1cd1f3054af86ebe60df96989c6a414dd87e27ad16950eee420bea/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:b0d95340658b9d2f11d9697f59b3814a9d3bb4b7a7c20b131df4bcef464037c0", size = 1782841, upload-time = "2026-01-03T17:32:11.445Z" },
+ { url = "https://files.pythonhosted.org/packages/88/0d/d98a9367b38912384a17e287850f5695c528cff0f14f791ce8ee2e4f7796/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:a1e53262fd202e4b40b70c3aff944a8155059beedc8a89bba9dc1f9ef06a1b56", size = 1795193, upload-time = "2026-01-03T17:32:13.705Z" },
+ { url = "https://files.pythonhosted.org/packages/43/a5/a2dfd1f5ff5581632c7f6a30e1744deda03808974f94f6534241ef60c751/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:d60ac9663f44168038586cab2157e122e46bdef09e9368b37f2d82d354c23f72", size = 1621979, upload-time = "2026-01-03T17:32:15.965Z" },
+ { url = "https://files.pythonhosted.org/packages/fa/f0/12973c382ae7c1cccbc4417e129c5bf54c374dfb85af70893646e1f0e749/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:90751b8eed69435bac9ff4e3d2f6b3af1f57e37ecb0fbeee59c0174c9e2d41df", size = 1822193, upload-time = "2026-01-03T17:32:18.219Z" },
+ { url = "https://files.pythonhosted.org/packages/3c/5f/24155e30ba7f8c96918af1350eb0663e2430aad9e001c0489d89cd708ab1/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fc353029f176fd2b3ec6cfc71be166aba1936fe5d73dd1992ce289ca6647a9aa", size = 1769801, upload-time = "2026-01-03T17:32:20.25Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/f8/7314031ff5c10e6ece114da79b338ec17eeff3a079e53151f7e9f43c4723/aiohttp-3.13.3-cp314-cp314t-win32.whl", hash = "sha256:2e41b18a58da1e474a057b3d35248d8320029f61d70a37629535b16a0c8f3767", size = 466523, upload-time = "2026-01-03T17:32:22.215Z" },
+ { url = "https://files.pythonhosted.org/packages/b4/63/278a98c715ae467624eafe375542d8ba9b4383a016df8fdefe0ae28382a7/aiohttp-3.13.3-cp314-cp314t-win_amd64.whl", hash = "sha256:44531a36aa2264a1860089ffd4dce7baf875ee5a6079d5fb42e261c704ef7344", size = 499694, upload-time = "2026-01-03T17:32:24.546Z" },
+]
+
+[[package]]
+name = "aiosignal"
+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 = [
+ { url = "https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", size = 7490, upload-time = "2025-07-03T22:54:42.156Z" },
+]
+
+[[package]]
+name = "annotated-types"
+version = "0.7.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" },
+]
+
+[[package]]
+name = "anyio"
+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 = [
+ { url = "https://files.pythonhosted.org/packages/38/0e/27be9fdef66e72d64c0cdc3cc2823101b80585f8119b5c112c2e8f5f7dab/anyio-4.12.1-py3-none-any.whl", hash = "sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c", size = 113592, upload-time = "2026-01-06T11:45:19.497Z" },
+]
+
+[[package]]
+name = "attrs"
+version = "25.4.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/6b/5c/685e6633917e101e5dcb62b9dd76946cbb57c26e133bae9e0cd36033c0a9/attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11", size = 934251, upload-time = "2025-10-06T13:54:44.725Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" },
+]
+
+[[package]]
+name = "certifi"
+version = "2026.1.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/e0/2d/a891ca51311197f6ad14a7ef42e2399f36cf2f9bd44752b3dc4eab60fdc5/certifi-2026.1.4.tar.gz", hash = "sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120", size = 154268, upload-time = "2026-01-04T02:42:41.825Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl", hash = "sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c", size = 152900, upload-time = "2026-01-04T02:42:40.15Z" },
+]
+
+[[package]]
+name = "charset-normalizer"
+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/ed/27/c6491ff4954e58a10f69ad90aca8a1b6fe9c5d3c6f380907af3c37435b59/charset_normalizer-3.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8", size = 206988, upload-time = "2025-10-14T04:40:33.79Z" },
+ { url = "https://files.pythonhosted.org/packages/94/59/2e87300fe67ab820b5428580a53cad894272dbb97f38a7a814a2a1ac1011/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0", size = 147324, upload-time = "2025-10-14T04:40:34.961Z" },
+ { url = "https://files.pythonhosted.org/packages/07/fb/0cf61dc84b2b088391830f6274cb57c82e4da8bbc2efeac8c025edb88772/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3", size = 142742, upload-time = "2025-10-14T04:40:36.105Z" },
+ { url = "https://files.pythonhosted.org/packages/62/8b/171935adf2312cd745d290ed93cf16cf0dfe320863ab7cbeeae1dcd6535f/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc", size = 160863, upload-time = "2025-10-14T04:40:37.188Z" },
+ { url = "https://files.pythonhosted.org/packages/09/73/ad875b192bda14f2173bfc1bc9a55e009808484a4b256748d931b6948442/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897", size = 157837, upload-time = "2025-10-14T04:40:38.435Z" },
+ { url = "https://files.pythonhosted.org/packages/6d/fc/de9cce525b2c5b94b47c70a4b4fb19f871b24995c728e957ee68ab1671ea/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381", size = 151550, upload-time = "2025-10-14T04:40:40.053Z" },
+ { url = "https://files.pythonhosted.org/packages/55/c2/43edd615fdfba8c6f2dfbd459b25a6b3b551f24ea21981e23fb768503ce1/charset_normalizer-3.4.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815", size = 149162, upload-time = "2025-10-14T04:40:41.163Z" },
+ { url = "https://files.pythonhosted.org/packages/03/86/bde4ad8b4d0e9429a4e82c1e8f5c659993a9a863ad62c7df05cf7b678d75/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0", size = 150019, upload-time = "2025-10-14T04:40:42.276Z" },
+ { url = "https://files.pythonhosted.org/packages/1f/86/a151eb2af293a7e7bac3a739b81072585ce36ccfb4493039f49f1d3cae8c/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161", size = 143310, upload-time = "2025-10-14T04:40:43.439Z" },
+ { url = "https://files.pythonhosted.org/packages/b5/fe/43dae6144a7e07b87478fdfc4dbe9efd5defb0e7ec29f5f58a55aeef7bf7/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4", size = 162022, upload-time = "2025-10-14T04:40:44.547Z" },
+ { url = "https://files.pythonhosted.org/packages/80/e6/7aab83774f5d2bca81f42ac58d04caf44f0cc2b65fc6db2b3b2e8a05f3b3/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89", size = 149383, upload-time = "2025-10-14T04:40:46.018Z" },
+ { url = "https://files.pythonhosted.org/packages/4f/e8/b289173b4edae05c0dde07f69f8db476a0b511eac556dfe0d6bda3c43384/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569", size = 159098, upload-time = "2025-10-14T04:40:47.081Z" },
+ { url = "https://files.pythonhosted.org/packages/d8/df/fe699727754cae3f8478493c7f45f777b17c3ef0600e28abfec8619eb49c/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224", size = 152991, upload-time = "2025-10-14T04:40:48.246Z" },
+ { url = "https://files.pythonhosted.org/packages/1a/86/584869fe4ddb6ffa3bd9f491b87a01568797fb9bd8933f557dba9771beaf/charset_normalizer-3.4.4-cp311-cp311-win32.whl", hash = "sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a", size = 99456, upload-time = "2025-10-14T04:40:49.376Z" },
+ { url = "https://files.pythonhosted.org/packages/65/f6/62fdd5feb60530f50f7e38b4f6a1d5203f4d16ff4f9f0952962c044e919a/charset_normalizer-3.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016", size = 106978, upload-time = "2025-10-14T04:40:50.844Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/9d/0710916e6c82948b3be62d9d398cb4fcf4e97b56d6a6aeccd66c4b2f2bd5/charset_normalizer-3.4.4-cp311-cp311-win_arm64.whl", hash = "sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1", size = 99969, upload-time = "2025-10-14T04:40:52.272Z" },
+ { 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" },
+ { url = "https://files.pythonhosted.org/packages/ba/33/0ad65587441fc730dc7bd90e9716b30b4702dc7b617e6ba4997dc8651495/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14", size = 160779, upload-time = "2025-10-14T04:41:37.229Z" },
+ { url = "https://files.pythonhosted.org/packages/67/ed/331d6b249259ee71ddea93f6f2f0a56cfebd46938bde6fcc6f7b9a3d0e09/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191", size = 159035, upload-time = "2025-10-14T04:41:38.368Z" },
+ { url = "https://files.pythonhosted.org/packages/67/ff/f6b948ca32e4f2a4576aa129d8bed61f2e0543bf9f5f2b7fc3758ed005c9/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838", size = 152542, upload-time = "2025-10-14T04:41:39.862Z" },
+ { url = "https://files.pythonhosted.org/packages/16/85/276033dcbcc369eb176594de22728541a925b2632f9716428c851b149e83/charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6", size = 149524, upload-time = "2025-10-14T04:41:41.319Z" },
+ { url = "https://files.pythonhosted.org/packages/9e/f2/6a2a1f722b6aba37050e626530a46a68f74e63683947a8acff92569f979a/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e", size = 150395, upload-time = "2025-10-14T04:41:42.539Z" },
+ { url = "https://files.pythonhosted.org/packages/60/bb/2186cb2f2bbaea6338cad15ce23a67f9b0672929744381e28b0592676824/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c", size = 143680, upload-time = "2025-10-14T04:41:43.661Z" },
+ { url = "https://files.pythonhosted.org/packages/7d/a5/bf6f13b772fbb2a90360eb620d52ed8f796f3c5caee8398c3b2eb7b1c60d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090", size = 162045, upload-time = "2025-10-14T04:41:44.821Z" },
+ { url = "https://files.pythonhosted.org/packages/df/c5/d1be898bf0dc3ef9030c3825e5d3b83f2c528d207d246cbabe245966808d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152", size = 149687, upload-time = "2025-10-14T04:41:46.442Z" },
+ { url = "https://files.pythonhosted.org/packages/a5/42/90c1f7b9341eef50c8a1cb3f098ac43b0508413f33affd762855f67a410e/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828", size = 160014, upload-time = "2025-10-14T04:41:47.631Z" },
+ { url = "https://files.pythonhosted.org/packages/76/be/4d3ee471e8145d12795ab655ece37baed0929462a86e72372fd25859047c/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec", size = 154044, upload-time = "2025-10-14T04:41:48.81Z" },
+ { url = "https://files.pythonhosted.org/packages/b0/6f/8f7af07237c34a1defe7defc565a9bc1807762f672c0fde711a4b22bf9c0/charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9", size = 99940, upload-time = "2025-10-14T04:41:49.946Z" },
+ { url = "https://files.pythonhosted.org/packages/4b/51/8ade005e5ca5b0d80fb4aff72a3775b325bdc3d27408c8113811a7cbe640/charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c", size = 107104, upload-time = "2025-10-14T04:41:51.051Z" },
+ { url = "https://files.pythonhosted.org/packages/da/5f/6b8f83a55bb8278772c5ae54a577f3099025f9ade59d0136ac24a0df4bde/charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2", size = 100743, upload-time = "2025-10-14T04:41:52.122Z" },
+ { url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" },
+]
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
+]
+
+[[package]]
+name = "deep-research-demos"
+version = "0.1.0"
+source = { virtual = "." }
+dependencies = [
+ { name = "langchain-openai" },
+ { name = "langchain-tavily" },
+ { name = "langgraph" },
+ { name = "pydantic" },
+ { name = "pytest" },
+ { name = "python-dotenv" },
+ { name = "tavily-python" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "langchain-openai", specifier = ">=0.3.0" },
+ { name = "langchain-tavily", specifier = ">=0.1.0" },
+ { name = "langgraph", specifier = ">=0.2.0" },
+ { name = "pydantic", specifier = ">=2.0" },
+ { name = "pytest", specifier = ">=8.0" },
+ { name = "python-dotenv", specifier = ">=1.0.0" },
+ { name = "tavily-python", specifier = ">=0.5.0" },
+]
+
+[[package]]
+name = "distro"
+version = "1.9.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/fc/f8/98eea607f65de6527f8a2e8885fc8015d3e6f5775df186e443e0964a11c3/distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed", size = 60722, upload-time = "2023-12-24T09:54:32.31Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277, upload-time = "2023-12-24T09:54:30.421Z" },
+]
+
+[[package]]
+name = "frozenlist"
+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/bc/03/077f869d540370db12165c0aa51640a873fb661d8b315d1d4d67b284d7ac/frozenlist-1.8.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:09474e9831bc2b2199fad6da3c14c7b0fbdd377cce9d3d77131be28906cb7d84", size = 86912, upload-time = "2025-10-06T05:35:45.98Z" },
+ { url = "https://files.pythonhosted.org/packages/df/b5/7610b6bd13e4ae77b96ba85abea1c8cb249683217ef09ac9e0ae93f25a91/frozenlist-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:17c883ab0ab67200b5f964d2b9ed6b00971917d5d8a92df149dc2c9779208ee9", size = 50046, upload-time = "2025-10-06T05:35:47.009Z" },
+ { url = "https://files.pythonhosted.org/packages/6e/ef/0e8f1fe32f8a53dd26bdd1f9347efe0778b0fddf62789ea683f4cc7d787d/frozenlist-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fa47e444b8ba08fffd1c18e8cdb9a75db1b6a27f17507522834ad13ed5922b93", size = 50119, upload-time = "2025-10-06T05:35:48.38Z" },
+ { url = "https://files.pythonhosted.org/packages/11/b1/71a477adc7c36e5fb628245dfbdea2166feae310757dea848d02bd0689fd/frozenlist-1.8.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2552f44204b744fba866e573be4c1f9048d6a324dfe14475103fd51613eb1d1f", size = 231067, upload-time = "2025-10-06T05:35:49.97Z" },
+ { url = "https://files.pythonhosted.org/packages/45/7e/afe40eca3a2dc19b9904c0f5d7edfe82b5304cb831391edec0ac04af94c2/frozenlist-1.8.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:957e7c38f250991e48a9a73e6423db1bb9dd14e722a10f6b8bb8e16a0f55f695", size = 233160, upload-time = "2025-10-06T05:35:51.729Z" },
+ { url = "https://files.pythonhosted.org/packages/a6/aa/7416eac95603ce428679d273255ffc7c998d4132cfae200103f164b108aa/frozenlist-1.8.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8585e3bb2cdea02fc88ffa245069c36555557ad3609e83be0ec71f54fd4abb52", size = 228544, upload-time = "2025-10-06T05:35:53.246Z" },
+ { url = "https://files.pythonhosted.org/packages/8b/3d/2a2d1f683d55ac7e3875e4263d28410063e738384d3adc294f5ff3d7105e/frozenlist-1.8.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:edee74874ce20a373d62dc28b0b18b93f645633c2943fd90ee9d898550770581", size = 243797, upload-time = "2025-10-06T05:35:54.497Z" },
+ { url = "https://files.pythonhosted.org/packages/78/1e/2d5565b589e580c296d3bb54da08d206e797d941a83a6fdea42af23be79c/frozenlist-1.8.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c9a63152fe95756b85f31186bddf42e4c02c6321207fd6601a1c89ebac4fe567", size = 247923, upload-time = "2025-10-06T05:35:55.861Z" },
+ { url = "https://files.pythonhosted.org/packages/aa/c3/65872fcf1d326a7f101ad4d86285c403c87be7d832b7470b77f6d2ed5ddc/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b6db2185db9be0a04fecf2f241c70b63b1a242e2805be291855078f2b404dd6b", size = 230886, upload-time = "2025-10-06T05:35:57.399Z" },
+ { url = "https://files.pythonhosted.org/packages/a0/76/ac9ced601d62f6956f03cc794f9e04c81719509f85255abf96e2510f4265/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f4be2e3d8bc8aabd566f8d5b8ba7ecc09249d74ba3c9ed52e54dc23a293f0b92", size = 245731, upload-time = "2025-10-06T05:35:58.563Z" },
+ { url = "https://files.pythonhosted.org/packages/b9/49/ecccb5f2598daf0b4a1415497eba4c33c1e8ce07495eb07d2860c731b8d5/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c8d1634419f39ea6f5c427ea2f90ca85126b54b50837f31497f3bf38266e853d", size = 241544, upload-time = "2025-10-06T05:35:59.719Z" },
+ { url = "https://files.pythonhosted.org/packages/53/4b/ddf24113323c0bbcc54cb38c8b8916f1da7165e07b8e24a717b4a12cbf10/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:1a7fa382a4a223773ed64242dbe1c9c326ec09457e6b8428efb4118c685c3dfd", size = 241806, upload-time = "2025-10-06T05:36:00.959Z" },
+ { url = "https://files.pythonhosted.org/packages/a7/fb/9b9a084d73c67175484ba2789a59f8eebebd0827d186a8102005ce41e1ba/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:11847b53d722050808926e785df837353bd4d75f1d494377e59b23594d834967", size = 229382, upload-time = "2025-10-06T05:36:02.22Z" },
+ { url = "https://files.pythonhosted.org/packages/95/a3/c8fb25aac55bf5e12dae5c5aa6a98f85d436c1dc658f21c3ac73f9fa95e5/frozenlist-1.8.0-cp311-cp311-win32.whl", hash = "sha256:27c6e8077956cf73eadd514be8fb04d77fc946a7fe9f7fe167648b0b9085cc25", size = 39647, upload-time = "2025-10-06T05:36:03.409Z" },
+ { url = "https://files.pythonhosted.org/packages/0a/f5/603d0d6a02cfd4c8f2a095a54672b3cf967ad688a60fb9faf04fc4887f65/frozenlist-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:ac913f8403b36a2c8610bbfd25b8013488533e71e62b4b4adce9c86c8cea905b", size = 44064, upload-time = "2025-10-06T05:36:04.368Z" },
+ { url = "https://files.pythonhosted.org/packages/5d/16/c2c9ab44e181f043a86f9a8f84d5124b62dbcb3a02c0977ec72b9ac1d3e0/frozenlist-1.8.0-cp311-cp311-win_arm64.whl", hash = "sha256:d4d3214a0f8394edfa3e303136d0575eece0745ff2b47bd2cb2e66dd92d4351a", size = 39937, upload-time = "2025-10-06T05:36:05.669Z" },
+ { 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" },
+ { url = "https://files.pythonhosted.org/packages/a7/b2/fabede9fafd976b991e9f1b9c8c873ed86f202889b864756f240ce6dd855/frozenlist-1.8.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:cba69cb73723c3f329622e34bdbf5ce1f80c21c290ff04256cff1cd3c2036ed2", size = 231298, upload-time = "2025-10-06T05:37:11.993Z" },
+ { url = "https://files.pythonhosted.org/packages/3a/3b/d9b1e0b0eed36e70477ffb8360c49c85c8ca8ef9700a4e6711f39a6e8b45/frozenlist-1.8.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:778a11b15673f6f1df23d9586f83c4846c471a8af693a22e066508b77d201ec8", size = 232015, upload-time = "2025-10-06T05:37:13.194Z" },
+ { url = "https://files.pythonhosted.org/packages/dc/94/be719d2766c1138148564a3960fc2c06eb688da592bdc25adcf856101be7/frozenlist-1.8.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0325024fe97f94c41c08872db482cf8ac4800d80e79222c6b0b7b162d5b13686", size = 225038, upload-time = "2025-10-06T05:37:14.577Z" },
+ { url = "https://files.pythonhosted.org/packages/e4/09/6712b6c5465f083f52f50cf74167b92d4ea2f50e46a9eea0523d658454ae/frozenlist-1.8.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:97260ff46b207a82a7567b581ab4190bd4dfa09f4db8a8b49d1a958f6aa4940e", size = 240130, upload-time = "2025-10-06T05:37:15.781Z" },
+ { url = "https://files.pythonhosted.org/packages/f8/d4/cd065cdcf21550b54f3ce6a22e143ac9e4836ca42a0de1022da8498eac89/frozenlist-1.8.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:54b2077180eb7f83dd52c40b2750d0a9f175e06a42e3213ce047219de902717a", size = 242845, upload-time = "2025-10-06T05:37:17.037Z" },
+ { url = "https://files.pythonhosted.org/packages/62/c3/f57a5c8c70cd1ead3d5d5f776f89d33110b1addae0ab010ad774d9a44fb9/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2f05983daecab868a31e1da44462873306d3cbfd76d1f0b5b69c473d21dbb128", size = 229131, upload-time = "2025-10-06T05:37:18.221Z" },
+ { url = "https://files.pythonhosted.org/packages/6c/52/232476fe9cb64f0742f3fde2b7d26c1dac18b6d62071c74d4ded55e0ef94/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:33f48f51a446114bc5d251fb2954ab0164d5be02ad3382abcbfe07e2531d650f", size = 240542, upload-time = "2025-10-06T05:37:19.771Z" },
+ { url = "https://files.pythonhosted.org/packages/5f/85/07bf3f5d0fb5414aee5f47d33c6f5c77bfe49aac680bfece33d4fdf6a246/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:154e55ec0655291b5dd1b8731c637ecdb50975a2ae70c606d100750a540082f7", size = 237308, upload-time = "2025-10-06T05:37:20.969Z" },
+ { url = "https://files.pythonhosted.org/packages/11/99/ae3a33d5befd41ac0ca2cc7fd3aa707c9c324de2e89db0e0f45db9a64c26/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:4314debad13beb564b708b4a496020e5306c7333fa9a3ab90374169a20ffab30", size = 238210, upload-time = "2025-10-06T05:37:22.252Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/60/b1d2da22f4970e7a155f0adde9b1435712ece01b3cd45ba63702aea33938/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:073f8bf8becba60aa931eb3bc420b217bb7d5b8f4750e6f8b3be7f3da85d38b7", size = 231972, upload-time = "2025-10-06T05:37:23.5Z" },
+ { url = "https://files.pythonhosted.org/packages/3f/ab/945b2f32de889993b9c9133216c068b7fcf257d8595a0ac420ac8677cab0/frozenlist-1.8.0-cp314-cp314-win32.whl", hash = "sha256:bac9c42ba2ac65ddc115d930c78d24ab8d4f465fd3fc473cdedfccadb9429806", size = 40536, upload-time = "2025-10-06T05:37:25.581Z" },
+ { url = "https://files.pythonhosted.org/packages/59/ad/9caa9b9c836d9ad6f067157a531ac48b7d36499f5036d4141ce78c230b1b/frozenlist-1.8.0-cp314-cp314-win_amd64.whl", hash = "sha256:3e0761f4d1a44f1d1a47996511752cf3dcec5bbdd9cc2b4fe595caf97754b7a0", size = 44330, upload-time = "2025-10-06T05:37:26.928Z" },
+ { url = "https://files.pythonhosted.org/packages/82/13/e6950121764f2676f43534c555249f57030150260aee9dcf7d64efda11dd/frozenlist-1.8.0-cp314-cp314-win_arm64.whl", hash = "sha256:d1eaff1d00c7751b7c6662e9c5ba6eb2c17a2306ba5e2a37f24ddf3cc953402b", size = 40627, upload-time = "2025-10-06T05:37:28.075Z" },
+ { url = "https://files.pythonhosted.org/packages/c0/c7/43200656ecc4e02d3f8bc248df68256cd9572b3f0017f0a0c4e93440ae23/frozenlist-1.8.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:d3bb933317c52d7ea5004a1c442eef86f426886fba134ef8cf4226ea6ee1821d", size = 89238, upload-time = "2025-10-06T05:37:29.373Z" },
+ { url = "https://files.pythonhosted.org/packages/d1/29/55c5f0689b9c0fb765055629f472c0de484dcaf0acee2f7707266ae3583c/frozenlist-1.8.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8009897cdef112072f93a0efdce29cd819e717fd2f649ee3016efd3cd885a7ed", size = 50738, upload-time = "2025-10-06T05:37:30.792Z" },
+ { url = "https://files.pythonhosted.org/packages/ba/7d/b7282a445956506fa11da8c2db7d276adcbf2b17d8bb8407a47685263f90/frozenlist-1.8.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2c5dcbbc55383e5883246d11fd179782a9d07a986c40f49abe89ddf865913930", size = 51739, upload-time = "2025-10-06T05:37:32.127Z" },
+ { url = "https://files.pythonhosted.org/packages/62/1c/3d8622e60d0b767a5510d1d3cf21065b9db874696a51ea6d7a43180a259c/frozenlist-1.8.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:39ecbc32f1390387d2aa4f5a995e465e9e2f79ba3adcac92d68e3e0afae6657c", size = 284186, upload-time = "2025-10-06T05:37:33.21Z" },
+ { url = "https://files.pythonhosted.org/packages/2d/14/aa36d5f85a89679a85a1d44cd7a6657e0b1c75f61e7cad987b203d2daca8/frozenlist-1.8.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92db2bf818d5cc8d9c1f1fc56b897662e24ea5adb36ad1f1d82875bd64e03c24", size = 292196, upload-time = "2025-10-06T05:37:36.107Z" },
+ { url = "https://files.pythonhosted.org/packages/05/23/6bde59eb55abd407d34f77d39a5126fb7b4f109a3f611d3929f14b700c66/frozenlist-1.8.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2dc43a022e555de94c3b68a4ef0b11c4f747d12c024a520c7101709a2144fb37", size = 273830, upload-time = "2025-10-06T05:37:37.663Z" },
+ { url = "https://files.pythonhosted.org/packages/d2/3f/22cff331bfad7a8afa616289000ba793347fcd7bc275f3b28ecea2a27909/frozenlist-1.8.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cb89a7f2de3602cfed448095bab3f178399646ab7c61454315089787df07733a", size = 294289, upload-time = "2025-10-06T05:37:39.261Z" },
+ { url = "https://files.pythonhosted.org/packages/a4/89/5b057c799de4838b6c69aa82b79705f2027615e01be996d2486a69ca99c4/frozenlist-1.8.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:33139dc858c580ea50e7e60a1b0ea003efa1fd42e6ec7fdbad78fff65fad2fd2", size = 300318, upload-time = "2025-10-06T05:37:43.213Z" },
+ { url = "https://files.pythonhosted.org/packages/30/de/2c22ab3eb2a8af6d69dc799e48455813bab3690c760de58e1bf43b36da3e/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:168c0969a329b416119507ba30b9ea13688fafffac1b7822802537569a1cb0ef", size = 282814, upload-time = "2025-10-06T05:37:45.337Z" },
+ { url = "https://files.pythonhosted.org/packages/59/f7/970141a6a8dbd7f556d94977858cfb36fa9b66e0892c6dd780d2219d8cd8/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:28bd570e8e189d7f7b001966435f9dac6718324b5be2990ac496cf1ea9ddb7fe", size = 291762, upload-time = "2025-10-06T05:37:46.657Z" },
+ { url = "https://files.pythonhosted.org/packages/c1/15/ca1adae83a719f82df9116d66f5bb28bb95557b3951903d39135620ef157/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b2a095d45c5d46e5e79ba1e5b9cb787f541a8dee0433836cea4b96a2c439dcd8", size = 289470, upload-time = "2025-10-06T05:37:47.946Z" },
+ { url = "https://files.pythonhosted.org/packages/ac/83/dca6dc53bf657d371fbc88ddeb21b79891e747189c5de990b9dfff2ccba1/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:eab8145831a0d56ec9c4139b6c3e594c7a83c2c8be25d5bcf2d86136a532287a", size = 289042, upload-time = "2025-10-06T05:37:49.499Z" },
+ { url = "https://files.pythonhosted.org/packages/96/52/abddd34ca99be142f354398700536c5bd315880ed0a213812bc491cff5e4/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:974b28cf63cc99dfb2188d8d222bc6843656188164848c4f679e63dae4b0708e", size = 283148, upload-time = "2025-10-06T05:37:50.745Z" },
+ { url = "https://files.pythonhosted.org/packages/af/d3/76bd4ed4317e7119c2b7f57c3f6934aba26d277acc6309f873341640e21f/frozenlist-1.8.0-cp314-cp314t-win32.whl", hash = "sha256:342c97bf697ac5480c0a7ec73cd700ecfa5a8a40ac923bd035484616efecc2df", size = 44676, upload-time = "2025-10-06T05:37:52.222Z" },
+ { url = "https://files.pythonhosted.org/packages/89/76/c615883b7b521ead2944bb3480398cbb07e12b7b4e4d073d3752eb721558/frozenlist-1.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:06be8f67f39c8b1dc671f5d83aaefd3358ae5cdcf8314552c57e7ed3e6475bdd", size = 49451, upload-time = "2025-10-06T05:37:53.425Z" },
+ { url = "https://files.pythonhosted.org/packages/e0/a3/5982da14e113d07b325230f95060e2169f5311b1017ea8af2a29b374c289/frozenlist-1.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:102e6314ca4da683dca92e3b1355490fed5f313b768500084fbe6371fddfdb79", size = 42507, upload-time = "2025-10-06T05:37:54.513Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/9a/e35b4a917281c0b8419d4207f4334c8e8c5dbf4f3f5f9ada73958d937dcc/frozenlist-1.8.0-py3-none-any.whl", hash = "sha256:0c18a16eab41e82c295618a77502e17b195883241c563b00f0aa5106fc4eaa0d", size = 13409, upload-time = "2025-10-06T05:38:16.721Z" },
+]
+
+[[package]]
+name = "h11"
+version = "0.16.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" },
+]
+
+[[package]]
+name = "httpcore"
+version = "1.0.9"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "certifi" },
+ { name = "h11" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" },
+]
+
+[[package]]
+name = "httpx"
+version = "0.28.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "anyio" },
+ { name = "certifi" },
+ { name = "httpcore" },
+ { name = "idna" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" },
+]
+
+[[package]]
+name = "idna"
+version = "3.11"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" },
+]
+
+[[package]]
+name = "iniconfig"
+version = "2.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
+]
+
+[[package]]
+name = "jiter"
+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/71/29/499f8c9eaa8a16751b1c0e45e6f5f1761d180da873d417996cc7bddc8eef/jiter-0.13.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:ea026e70a9a28ebbdddcbcf0f1323128a8db66898a06eaad3a4e62d2f554d096", size = 311157, upload-time = "2026-02-02T12:35:37.758Z" },
+ { url = "https://files.pythonhosted.org/packages/50/f6/566364c777d2ab450b92100bea11333c64c38d32caf8dc378b48e5b20c46/jiter-0.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:66aa3e663840152d18cc8ff1e4faad3dd181373491b9cfdc6004b92198d67911", size = 319729, upload-time = "2026-02-02T12:35:39.246Z" },
+ { url = "https://files.pythonhosted.org/packages/73/dd/560f13ec5e4f116d8ad2658781646cca91b617ae3b8758d4a5076b278f70/jiter-0.13.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3524798e70655ff19aec58c7d05adb1f074fecff62da857ea9be2b908b6d701", size = 354766, upload-time = "2026-02-02T12:35:40.662Z" },
+ { url = "https://files.pythonhosted.org/packages/7c/0d/061faffcfe94608cbc28a0d42a77a74222bdf5055ccdbe5fd2292b94f510/jiter-0.13.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ec7e287d7fbd02cb6e22f9a00dd9c9cd504c40a61f2c61e7e1f9690a82726b4c", size = 362587, upload-time = "2026-02-02T12:35:42.025Z" },
+ { url = "https://files.pythonhosted.org/packages/92/c9/c66a7864982fd38a9773ec6e932e0398d1262677b8c60faecd02ffb67bf3/jiter-0.13.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:47455245307e4debf2ce6c6e65a717550a0244231240dcf3b8f7d64e4c2f22f4", size = 487537, upload-time = "2026-02-02T12:35:43.459Z" },
+ { url = "https://files.pythonhosted.org/packages/6c/86/84eb4352cd3668f16d1a88929b5888a3fe0418ea8c1dfc2ad4e7bf6e069a/jiter-0.13.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ee9da221dca6e0429c2704c1b3655fe7b025204a71d4d9b73390c759d776d165", size = 373717, upload-time = "2026-02-02T12:35:44.928Z" },
+ { url = "https://files.pythonhosted.org/packages/6e/09/9fe4c159358176f82d4390407a03f506a8659ed13ca3ac93a843402acecf/jiter-0.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24ab43126d5e05f3d53a36a8e11eb2f23304c6c1117844aaaf9a0aa5e40b5018", size = 362683, upload-time = "2026-02-02T12:35:46.636Z" },
+ { url = "https://files.pythonhosted.org/packages/c9/5e/85f3ab9caca0c1d0897937d378b4a515cae9e119730563572361ea0c48ae/jiter-0.13.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9da38b4fedde4fb528c740c2564628fbab737166a0e73d6d46cb4bb5463ff411", size = 392345, upload-time = "2026-02-02T12:35:48.088Z" },
+ { url = "https://files.pythonhosted.org/packages/12/4c/05b8629ad546191939e6f0c2f17e29f542a398f4a52fb987bc70b6d1eb8b/jiter-0.13.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0b34c519e17658ed88d5047999a93547f8889f3c1824120c26ad6be5f27b6cf5", size = 517775, upload-time = "2026-02-02T12:35:49.482Z" },
+ { url = "https://files.pythonhosted.org/packages/4d/88/367ea2eb6bc582c7052e4baf5ddf57ebe5ab924a88e0e09830dfb585c02d/jiter-0.13.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d2a6394e6af690d462310a86b53c47ad75ac8c21dc79f120714ea449979cb1d3", size = 551325, upload-time = "2026-02-02T12:35:51.104Z" },
+ { url = "https://files.pythonhosted.org/packages/f3/12/fa377ffb94a2f28c41afaed093e0d70cfe512035d5ecb0cad0ae4792d35e/jiter-0.13.0-cp311-cp311-win32.whl", hash = "sha256:0f0c065695f616a27c920a56ad0d4fc46415ef8b806bf8fc1cacf25002bd24e1", size = 204709, upload-time = "2026-02-02T12:35:52.467Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/16/8e8203ce92f844dfcd3d9d6a5a7322c77077248dbb12da52d23193a839cd/jiter-0.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:0733312953b909688ae3c2d58d043aa040f9f1a6a75693defed7bc2cc4bf2654", size = 204560, upload-time = "2026-02-02T12:35:53.925Z" },
+ { url = "https://files.pythonhosted.org/packages/44/26/97cc40663deb17b9e13c3a5cf29251788c271b18ee4d262c8f94798b8336/jiter-0.13.0-cp311-cp311-win_arm64.whl", hash = "sha256:5d9b34ad56761b3bf0fbe8f7e55468704107608512350962d3317ffd7a4382d5", size = 189608, upload-time = "2026-02-02T12:35:55.304Z" },
+ { 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" },
+ { url = "https://files.pythonhosted.org/packages/c3/87/719eec4a3f0841dad99e3d3604ee4cba36af4419a76f3cb0b8e2e691ad67/jiter-0.13.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:682161a67adea11e3aae9038c06c8b4a9a71023228767477d683f69903ebc607", size = 366702, upload-time = "2026-02-02T12:36:48.871Z" },
+ { url = "https://files.pythonhosted.org/packages/d2/65/415f0a75cf6921e43365a1bc227c565cb949caca8b7532776e430cbaa530/jiter-0.13.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a13b68cd1cd8cc9de8f244ebae18ccb3e4067ad205220ef324c39181e23bbf66", size = 486319, upload-time = "2026-02-02T12:36:53.006Z" },
+ { url = "https://files.pythonhosted.org/packages/54/a2/9e12b48e82c6bbc6081fd81abf915e1443add1b13d8fc586e1d90bb02bb8/jiter-0.13.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87ce0f14c6c08892b610686ae8be350bf368467b6acd5085a5b65441e2bf36d2", size = 372289, upload-time = "2026-02-02T12:36:54.593Z" },
+ { url = "https://files.pythonhosted.org/packages/4e/c1/e4693f107a1789a239c759a432e9afc592366f04e901470c2af89cfd28e1/jiter-0.13.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c365005b05505a90d1c47856420980d0237adf82f70c4aff7aebd3c1cc143ad", size = 360165, upload-time = "2026-02-02T12:36:56.112Z" },
+ { url = "https://files.pythonhosted.org/packages/17/08/91b9ea976c1c758240614bd88442681a87672eebc3d9a6dde476874e706b/jiter-0.13.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1317fdffd16f5873e46ce27d0e0f7f4f90f0cdf1d86bf6abeaea9f63ca2c401d", size = 389634, upload-time = "2026-02-02T12:36:57.495Z" },
+ { url = "https://files.pythonhosted.org/packages/18/23/58325ef99390d6d40427ed6005bf1ad54f2577866594bcf13ce55675f87d/jiter-0.13.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:c05b450d37ba0c9e21c77fef1f205f56bcee2330bddca68d344baebfc55ae0df", size = 514933, upload-time = "2026-02-02T12:36:58.909Z" },
+ { url = "https://files.pythonhosted.org/packages/5b/25/69f1120c7c395fd276c3996bb8adefa9c6b84c12bb7111e5c6ccdcd8526d/jiter-0.13.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:775e10de3849d0631a97c603f996f518159272db00fdda0a780f81752255ee9d", size = 548842, upload-time = "2026-02-02T12:37:00.433Z" },
+ { url = "https://files.pythonhosted.org/packages/18/05/981c9669d86850c5fbb0d9e62bba144787f9fba84546ba43d624ee27ef29/jiter-0.13.0-cp314-cp314-win32.whl", hash = "sha256:632bf7c1d28421c00dd8bbb8a3bac5663e1f57d5cd5ed962bce3c73bf62608e6", size = 202108, upload-time = "2026-02-02T12:37:01.718Z" },
+ { url = "https://files.pythonhosted.org/packages/8d/96/cdcf54dd0b0341db7d25413229888a346c7130bd20820530905fdb65727b/jiter-0.13.0-cp314-cp314-win_amd64.whl", hash = "sha256:f22ef501c3f87ede88f23f9b11e608581c14f04db59b6a801f354397ae13739f", size = 204027, upload-time = "2026-02-02T12:37:03.075Z" },
+ { url = "https://files.pythonhosted.org/packages/fb/f9/724bcaaab7a3cd727031fe4f6995cb86c4bd344909177c186699c8dec51a/jiter-0.13.0-cp314-cp314-win_arm64.whl", hash = "sha256:07b75fe09a4ee8e0c606200622e571e44943f47254f95e2436c8bdcaceb36d7d", size = 187199, upload-time = "2026-02-02T12:37:04.414Z" },
+ { url = "https://files.pythonhosted.org/packages/62/92/1661d8b9fd6a3d7a2d89831db26fe3c1509a287d83ad7838831c7b7a5c7e/jiter-0.13.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:964538479359059a35fb400e769295d4b315ae61e4105396d355a12f7fef09f0", size = 318423, upload-time = "2026-02-02T12:37:05.806Z" },
+ { url = "https://files.pythonhosted.org/packages/4f/3b/f77d342a54d4ebcd128e520fc58ec2f5b30a423b0fd26acdfc0c6fef8e26/jiter-0.13.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e104da1db1c0991b3eaed391ccd650ae8d947eab1480c733e5a3fb28d4313e40", size = 351438, upload-time = "2026-02-02T12:37:07.189Z" },
+ { url = "https://files.pythonhosted.org/packages/76/b3/ba9a69f0e4209bd3331470c723c2f5509e6f0482e416b612431a5061ed71/jiter-0.13.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0e3a5f0cde8ff433b8e88e41aa40131455420fb3649a3c7abdda6145f8cb7202", size = 364774, upload-time = "2026-02-02T12:37:08.579Z" },
+ { url = "https://files.pythonhosted.org/packages/b3/16/6cdb31fa342932602458dbb631bfbd47f601e03d2e4950740e0b2100b570/jiter-0.13.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:57aab48f40be1db920a582b30b116fe2435d184f77f0e4226f546794cedd9cf0", size = 487238, upload-time = "2026-02-02T12:37:10.066Z" },
+ { url = "https://files.pythonhosted.org/packages/ed/b1/956cc7abaca8d95c13aa8d6c9b3f3797241c246cd6e792934cc4c8b250d2/jiter-0.13.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7772115877c53f62beeb8fd853cab692dbc04374ef623b30f997959a4c0e7e95", size = 372892, upload-time = "2026-02-02T12:37:11.656Z" },
+ { url = "https://files.pythonhosted.org/packages/26/c4/97ecde8b1e74f67b8598c57c6fccf6df86ea7861ed29da84629cdbba76c4/jiter-0.13.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1211427574b17b633cfceba5040de8081e5abf114f7a7602f73d2e16f9fdaa59", size = 360309, upload-time = "2026-02-02T12:37:13.244Z" },
+ { url = "https://files.pythonhosted.org/packages/4b/d7/eabe3cf46715854ccc80be2cd78dd4c36aedeb30751dbf85a1d08c14373c/jiter-0.13.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7beae3a3d3b5212d3a55d2961db3c292e02e302feb43fce6a3f7a31b90ea6dfe", size = 389607, upload-time = "2026-02-02T12:37:14.881Z" },
+ { url = "https://files.pythonhosted.org/packages/df/2d/03963fc0804e6109b82decfb9974eb92df3797fe7222428cae12f8ccaa0c/jiter-0.13.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:e5562a0f0e90a6223b704163ea28e831bd3a9faa3512a711f031611e6b06c939", size = 514986, upload-time = "2026-02-02T12:37:16.326Z" },
+ { url = "https://files.pythonhosted.org/packages/f6/6c/8c83b45eb3eb1c1e18d841fe30b4b5bc5619d781267ca9bc03e005d8fd0a/jiter-0.13.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:6c26a424569a59140fb51160a56df13f438a2b0967365e987889186d5fc2f6f9", size = 548756, upload-time = "2026-02-02T12:37:17.736Z" },
+ { 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/79/b3/3c29819a27178d0e461a8571fb63c6ae38be6dc36b78b3ec2876bbd6a910/jiter-0.13.0-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b1cbfa133241d0e6bdab48dcdc2604e8ba81512f6bbd68ec3e8e1357dd3c316c", size = 307016, upload-time = "2026-02-02T12:37:42.755Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/ae/60993e4b07b1ac5ebe46da7aa99fdbb802eb986c38d26e3883ac0125c4e0/jiter-0.13.0-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:db367d8be9fad6e8ebbac4a7578b7af562e506211036cba2c06c3b998603c3d2", size = 305024, upload-time = "2026-02-02T12:37:44.774Z" },
+ { url = "https://files.pythonhosted.org/packages/77/fa/2227e590e9cf98803db2811f172b2d6460a21539ab73006f251c66f44b14/jiter-0.13.0-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45f6f8efb2f3b0603092401dc2df79fa89ccbc027aaba4174d2d4133ed661434", size = 339337, upload-time = "2026-02-02T12:37:46.668Z" },
+ { url = "https://files.pythonhosted.org/packages/2d/92/015173281f7eb96c0ef580c997da8ef50870d4f7f4c9e03c845a1d62ae04/jiter-0.13.0-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:597245258e6ad085d064780abfb23a284d418d3e61c57362d9449c6c7317ee2d", size = 346395, upload-time = "2026-02-02T12:37:48.09Z" },
+ { 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]]
+name = "jsonpatch"
+version = "1.33"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "jsonpointer" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/42/78/18813351fe5d63acad16aec57f94ec2b70a09e53ca98145589e185423873/jsonpatch-1.33.tar.gz", hash = "sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c", size = 21699, upload-time = "2023-06-26T12:07:29.144Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/73/07/02e16ed01e04a374e644b575638ec7987ae846d25ad97bcc9945a3ee4b0e/jsonpatch-1.33-py2.py3-none-any.whl", hash = "sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade", size = 12898, upload-time = "2023-06-16T21:01:28.466Z" },
+]
+
+[[package]]
+name = "jsonpointer"
+version = "3.0.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/6a/0a/eebeb1fa92507ea94016a2a790b93c2ae41a7e18778f85471dc54475ed25/jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef", size = 9114, upload-time = "2024-06-10T19:24:42.462Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942", size = 7595, upload-time = "2024-06-10T19:24:40.698Z" },
+]
+
+[[package]]
+name = "langchain"
+version = "1.2.8"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "langchain-core" },
+ { name = "langgraph" },
+ { name = "pydantic" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/52/b7/a1d95dbb58e5e82dbd05e3730e2d4b99f784a4c6d39435579a1c2b8a8d12/langchain-1.2.8.tar.gz", hash = "sha256:d2bc45f8279f6291b152f28df3bb060b27c9a71163fe2e2a1ac878bd314d0dec", size = 558326, upload-time = "2026-02-02T15:51:59.425Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/66/1a/e1cabc08d8b12349fa6a898f033cc6b00a9a031b470582f4a9eb4cf8e55b/langchain-1.2.8-py3-none-any.whl", hash = "sha256:74a9595420b90e2fd6dc42e323e5e6c9f2a5d059b0ab51e4ad383893b86f8fbe", size = 108986, upload-time = "2026-02-02T15:51:58.465Z" },
+]
+
+[[package]]
+name = "langchain-core"
+version = "1.2.8"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "jsonpatch" },
+ { name = "langsmith" },
+ { name = "packaging" },
+ { name = "pydantic" },
+ { name = "pyyaml" },
+ { name = "tenacity" },
+ { name = "typing-extensions" },
+ { name = "uuid-utils" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/75/cc/55bf57b83cbc164cbf84cbf0c5e4fb640d673546af131db70797b97b125b/langchain_core-1.2.8.tar.gz", hash = "sha256:76d933c3f4cfd8484d8131c39bf25f562e2df4d0d5fe3218e05ff773210713b6", size = 814506, upload-time = "2026-02-02T15:35:33.056Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cc/d4/37fef9639b701c1fb1eea9e68447b72d86852ca3dc3253cdfd9c0afe228d/langchain_core-1.2.8-py3-none-any.whl", hash = "sha256:c732301272d63cfbcd75d114540257678627878f11b87046241272a25ba12ea7", size = 495753, upload-time = "2026-02-02T15:35:31.284Z" },
+]
+
+[[package]]
+name = "langchain-openai"
+version = "1.1.7"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "langchain-core" },
+ { name = "openai" },
+ { name = "tiktoken" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/38/b7/30bfc4d1b658a9ee524bcce3b0b2ec9c45a11c853a13c4f0c9da9882784b/langchain_openai-1.1.7.tar.gz", hash = "sha256:f5ec31961ed24777548b63a5fe313548bc6e0eb9730d6552b8c6418765254c81", size = 1039134, upload-time = "2026-01-07T19:44:59.728Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/64/a1/50e7596aca775d8c3883eceeaf47489fac26c57c1abe243c00174f715a8a/langchain_openai-1.1.7-py3-none-any.whl", hash = "sha256:34e9cd686aac1a120d6472804422792bf8080a2103b5d21ee450c9e42d053815", size = 84753, upload-time = "2026-01-07T19:44:58.629Z" },
+]
+
+[[package]]
+name = "langchain-tavily"
+version = "0.2.17"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "aiohttp" },
+ { name = "langchain" },
+ { name = "langchain-core" },
+ { name = "requests" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/e6/32/f7b5487efbcd5fca5d4095f03dce7dcf0301ed81b2505d9888427c03619b/langchain_tavily-0.2.17.tar.gz", hash = "sha256:738abd790c50f19565023ad279c8e47e87e1aeb971797fec30a614b418ae6503", size = 25298, upload-time = "2026-01-18T13:09:04.112Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/35/f9/bb6f1cea2a19215e4169a3bcec3af707ff947cf62f6ef7d28e7280f03e29/langchain_tavily-0.2.17-py3-none-any.whl", hash = "sha256:da4e5e7e328d054dc70a9c934afa1d1e62038612106647ff81ad8bfbe3622256", size = 30734, upload-time = "2026-01-18T13:09:03.1Z" },
+]
+
+[[package]]
+name = "langgraph"
+version = "1.0.7"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "langchain-core" },
+ { name = "langgraph-checkpoint" },
+ { name = "langgraph-prebuilt" },
+ { name = "langgraph-sdk" },
+ { name = "pydantic" },
+ { name = "xxhash" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/72/5b/f72655717c04e33d3b62f21b166dc063d192b53980e9e3be0e2a117f1c9f/langgraph-1.0.7.tar.gz", hash = "sha256:0cfdfee51e6e8cfe503ecc7367c73933437c505b03fa10a85c710975c8182d9a", size = 497098, upload-time = "2026-01-22T16:57:47.303Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7e/0e/fe80144e3e4048e5d19ccdb91ac547c1a7dc3da8dbd1443e210048194c14/langgraph-1.0.7-py3-none-any.whl", hash = "sha256:9d68e8f8dd8f3de2fec45f9a06de05766d9b075b78fb03171779893b7a52c4d2", size = 157353, upload-time = "2026-01-22T16:57:45.997Z" },
+]
+
+[[package]]
+name = "langgraph-checkpoint"
+version = "4.0.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "langchain-core" },
+ { name = "ormsgpack" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/98/76/55a18c59dedf39688d72c4b06af73a5e3ea0d1a01bc867b88fbf0659f203/langgraph_checkpoint-4.0.0.tar.gz", hash = "sha256:814d1bd050fac029476558d8e68d87bce9009a0262d04a2c14b918255954a624", size = 137320, upload-time = "2026-01-12T20:30:26.38Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/4a/de/ddd53b7032e623f3c7bcdab2b44e8bf635e468f62e10e5ff1946f62c9356/langgraph_checkpoint-4.0.0-py3-none-any.whl", hash = "sha256:3fa9b2635a7c5ac28b338f631abf6a030c3b508b7b9ce17c22611513b589c784", size = 46329, upload-time = "2026-01-12T20:30:25.2Z" },
+]
+
+[[package]]
+name = "langgraph-prebuilt"
+version = "1.0.7"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "langchain-core" },
+ { name = "langgraph-checkpoint" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/a7/59/711aecd1a50999456850dc328f3cad72b4372d8218838d8d5326f80cb76f/langgraph_prebuilt-1.0.7.tar.gz", hash = "sha256:38e097e06de810de4d0e028ffc0e432bb56d1fb417620fb1dfdc76c5e03e4bf9", size = 163692, upload-time = "2026-01-22T16:45:22.801Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/47/49/5e37abb3f38a17a3487634abc2a5da87c208cc1d14577eb8d7184b25c886/langgraph_prebuilt-1.0.7-py3-none-any.whl", hash = "sha256:e14923516504405bb5edc3977085bc9622c35476b50c1808544490e13871fe7c", size = 35324, upload-time = "2026-01-22T16:45:21.784Z" },
+]
+
+[[package]]
+name = "langgraph-sdk"
+version = "0.3.3"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "httpx" },
+ { name = "orjson" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/c3/0f/ed0634c222eed48a31ba48eab6881f94ad690d65e44fe7ca838240a260c1/langgraph_sdk-0.3.3.tar.gz", hash = "sha256:c34c3dce3b6848755eb61f0c94369d1ba04aceeb1b76015db1ea7362c544fb26", size = 130589, upload-time = "2026-01-13T00:30:43.894Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/6e/be/4ad511bacfdd854afb12974f407cb30010dceb982dc20c55491867b34526/langgraph_sdk-0.3.3-py3-none-any.whl", hash = "sha256:a52ebaf09d91143e55378bb2d0b033ed98f57f48c9ad35c8f81493b88705fc7b", size = 67021, upload-time = "2026-01-13T00:30:42.264Z" },
+]
+
+[[package]]
+name = "langsmith"
+version = "0.6.8"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "httpx" },
+ { name = "orjson", marker = "platform_python_implementation != 'PyPy'" },
+ { name = "packaging" },
+ { name = "pydantic" },
+ { name = "requests" },
+ { name = "requests-toolbelt" },
+ { name = "uuid-utils" },
+ { name = "xxhash" },
+ { name = "zstandard" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/8e/15/35f49a0b2efd33002fdcb9a7b0bdb65d77e40b4739104ffe843a3479874a/langsmith-0.6.8.tar.gz", hash = "sha256:3a7eb7155f2839dc729a5aa5b0bfc4aa1cb617b09a2290cf77031041271a7cdf", size = 973475, upload-time = "2026-02-02T23:20:02.208Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cd/2d/2389e65522ebeab17489df72b4fabcfc661fced8af178aa6c2bc3b9afff5/langsmith-0.6.8-py3-none-any.whl", hash = "sha256:d17da18aeef15fdb4c3baec348bad64056591d785629cd5ba4846fd93cab166b", size = 319165, upload-time = "2026-02-02T23:20:00.456Z" },
+]
+
+[[package]]
+name = "multidict"
+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/ce/f1/a90635c4f88fb913fbf4ce660b83b7445b7a02615bda034b2f8eb38fd597/multidict-6.7.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7ff981b266af91d7b4b3793ca3382e53229088d193a85dfad6f5f4c27fc73e5d", size = 76626, upload-time = "2026-01-26T02:43:26.485Z" },
+ { url = "https://files.pythonhosted.org/packages/a6/9b/267e64eaf6fc637a15b35f5de31a566634a2740f97d8d094a69d34f524a4/multidict-6.7.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:844c5bca0b5444adb44a623fb0a1310c2f4cd41f402126bb269cd44c9b3f3e1e", size = 44706, upload-time = "2026-01-26T02:43:27.607Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/a4/d45caf2b97b035c57267791ecfaafbd59c68212004b3842830954bb4b02e/multidict-6.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f2a0a924d4c2e9afcd7ec64f9de35fcd96915149b2216e1cb2c10a56df483855", size = 44356, upload-time = "2026-01-26T02:43:28.661Z" },
+ { url = "https://files.pythonhosted.org/packages/fd/d2/0a36c8473f0cbaeadd5db6c8b72d15bbceeec275807772bfcd059bef487d/multidict-6.7.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8be1802715a8e892c784c0197c2ace276ea52702a0ede98b6310c8f255a5afb3", size = 244355, upload-time = "2026-01-26T02:43:31.165Z" },
+ { url = "https://files.pythonhosted.org/packages/5d/16/8c65be997fd7dd311b7d39c7b6e71a0cb449bad093761481eccbbe4b42a2/multidict-6.7.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2e2d2ed645ea29f31c4c7ea1552fcfd7cb7ba656e1eafd4134a6620c9f5fdd9e", size = 246433, upload-time = "2026-01-26T02:43:32.581Z" },
+ { url = "https://files.pythonhosted.org/packages/01/fb/4dbd7e848d2799c6a026ec88ad39cf2b8416aa167fcc903baa55ecaa045c/multidict-6.7.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:95922cee9a778659e91db6497596435777bd25ed116701a4c034f8e46544955a", size = 225376, upload-time = "2026-01-26T02:43:34.417Z" },
+ { url = "https://files.pythonhosted.org/packages/b6/8a/4a3a6341eac3830f6053062f8fbc9a9e54407c80755b3f05bc427295c2d0/multidict-6.7.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6b83cabdc375ffaaa15edd97eb7c0c672ad788e2687004990074d7d6c9b140c8", size = 257365, upload-time = "2026-01-26T02:43:35.741Z" },
+ { url = "https://files.pythonhosted.org/packages/f7/a2/dd575a69c1aa206e12d27d0770cdf9b92434b48a9ef0cd0d1afdecaa93c4/multidict-6.7.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:38fb49540705369bab8484db0689d86c0a33a0a9f2c1b197f506b71b4b6c19b0", size = 254747, upload-time = "2026-01-26T02:43:36.976Z" },
+ { url = "https://files.pythonhosted.org/packages/5a/56/21b27c560c13822ed93133f08aa6372c53a8e067f11fbed37b4adcdac922/multidict-6.7.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:439cbebd499f92e9aa6793016a8acaa161dfa749ae86d20960189f5398a19144", size = 246293, upload-time = "2026-01-26T02:43:38.258Z" },
+ { url = "https://files.pythonhosted.org/packages/5a/a4/23466059dc3854763423d0ad6c0f3683a379d97673b1b89ec33826e46728/multidict-6.7.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6d3bc717b6fe763b8be3f2bee2701d3c8eb1b2a8ae9f60910f1b2860c82b6c49", size = 242962, upload-time = "2026-01-26T02:43:40.034Z" },
+ { url = "https://files.pythonhosted.org/packages/1f/67/51dd754a3524d685958001e8fa20a0f5f90a6a856e0a9dcabff69be3dbb7/multidict-6.7.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:619e5a1ac57986dbfec9f0b301d865dddf763696435e2962f6d9cf2fdff2bb71", size = 237360, upload-time = "2026-01-26T02:43:41.752Z" },
+ { url = "https://files.pythonhosted.org/packages/64/3f/036dfc8c174934d4b55d86ff4f978e558b0e585cef70cfc1ad01adc6bf18/multidict-6.7.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0b38ebffd9be37c1170d33bc0f36f4f262e0a09bc1aac1c34c7aa51a7293f0b3", size = 245940, upload-time = "2026-01-26T02:43:43.042Z" },
+ { url = "https://files.pythonhosted.org/packages/3d/20/6214d3c105928ebc353a1c644a6ef1408bc5794fcb4f170bb524a3c16311/multidict-6.7.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:10ae39c9cfe6adedcdb764f5e8411d4a92b055e35573a2eaa88d3323289ef93c", size = 253502, upload-time = "2026-01-26T02:43:44.371Z" },
+ { url = "https://files.pythonhosted.org/packages/b1/e2/c653bc4ae1be70a0f836b82172d643fcf1dade042ba2676ab08ec08bff0f/multidict-6.7.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:25167cc263257660290fba06b9318d2026e3c910be240a146e1f66dd114af2b0", size = 247065, upload-time = "2026-01-26T02:43:45.745Z" },
+ { url = "https://files.pythonhosted.org/packages/c8/11/a854b4154cd3bd8b1fd375e8a8ca9d73be37610c361543d56f764109509b/multidict-6.7.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:128441d052254f42989ef98b7b6a6ecb1e6f708aa962c7984235316db59f50fa", size = 241870, upload-time = "2026-01-26T02:43:47.054Z" },
+ { url = "https://files.pythonhosted.org/packages/13/bf/9676c0392309b5fdae322333d22a829715b570edb9baa8016a517b55b558/multidict-6.7.1-cp311-cp311-win32.whl", hash = "sha256:d62b7f64ffde3b99d06b707a280db04fb3855b55f5a06df387236051d0668f4a", size = 41302, upload-time = "2026-01-26T02:43:48.753Z" },
+ { url = "https://files.pythonhosted.org/packages/c9/68/f16a3a8ba6f7b6dc92a1f19669c0810bd2c43fc5a02da13b1cbf8e253845/multidict-6.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:bdbf9f3b332abd0cdb306e7c2113818ab1e922dc84b8f8fd06ec89ed2a19ab8b", size = 45981, upload-time = "2026-01-26T02:43:49.921Z" },
+ { url = "https://files.pythonhosted.org/packages/ac/ad/9dd5305253fa00cd3c7555dbef69d5bf4133debc53b87ab8d6a44d411665/multidict-6.7.1-cp311-cp311-win_arm64.whl", hash = "sha256:b8c990b037d2fff2f4e33d3f21b9b531c5745b33a49a7d6dbe7a177266af44f6", size = 43159, upload-time = "2026-01-26T02:43:51.635Z" },
+ { 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" },
+ { url = "https://files.pythonhosted.org/packages/24/bb/2c0c2287963f4259c85e8bcbba9182ced8d7fca65c780c38e99e61629d11/multidict-6.7.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1e3a8bb24342a8201d178c3b4984c26ba81a577c80d4d525727427460a50c22d", size = 245132, upload-time = "2026-01-26T02:45:15.712Z" },
+ { url = "https://files.pythonhosted.org/packages/a7/f9/44d4b3064c65079d2467888794dea218d1601898ac50222ab8a9a8094460/multidict-6.7.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97231140a50f5d447d3164f994b86a0bed7cd016e2682f8650d6a9158e14fd31", size = 252420, upload-time = "2026-01-26T02:45:17.293Z" },
+ { url = "https://files.pythonhosted.org/packages/8b/13/78f7275e73fa17b24c9a51b0bd9d73ba64bb32d0ed51b02a746eb876abe7/multidict-6.7.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6b10359683bd8806a200fd2909e7c8ca3a7b24ec1d8132e483d58e791d881048", size = 233510, upload-time = "2026-01-26T02:45:19.356Z" },
+ { url = "https://files.pythonhosted.org/packages/4b/25/8167187f62ae3cbd52da7893f58cb036b47ea3fb67138787c76800158982/multidict-6.7.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:283ddac99f7ac25a4acadbf004cb5ae34480bbeb063520f70ce397b281859362", size = 264094, upload-time = "2026-01-26T02:45:20.834Z" },
+ { url = "https://files.pythonhosted.org/packages/a1/e7/69a3a83b7b030cf283fb06ce074a05a02322359783424d7edf0f15fe5022/multidict-6.7.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:538cec1e18c067d0e6103aa9a74f9e832904c957adc260e61cd9d8cf0c3b3d37", size = 260786, upload-time = "2026-01-26T02:45:22.818Z" },
+ { url = "https://files.pythonhosted.org/packages/fe/3b/8ec5074bcfc450fe84273713b4b0a0dd47c0249358f5d82eb8104ffe2520/multidict-6.7.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7eee46ccb30ff48a1e35bb818cc90846c6be2b68240e42a78599166722cea709", size = 248483, upload-time = "2026-01-26T02:45:24.368Z" },
+ { url = "https://files.pythonhosted.org/packages/48/5a/d5a99e3acbca0e29c5d9cba8f92ceb15dce78bab963b308ae692981e3a5d/multidict-6.7.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fa263a02f4f2dd2d11a7b1bb4362aa7cb1049f84a9235d31adf63f30143469a0", size = 248403, upload-time = "2026-01-26T02:45:25.982Z" },
+ { url = "https://files.pythonhosted.org/packages/35/48/e58cd31f6c7d5102f2a4bf89f96b9cf7e00b6c6f3d04ecc44417c00a5a3c/multidict-6.7.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:2e1425e2f99ec5bd36c15a01b690a1a2456209c5deed58f95469ffb46039ccbb", size = 240315, upload-time = "2026-01-26T02:45:27.487Z" },
+ { url = "https://files.pythonhosted.org/packages/94/33/1cd210229559cb90b6786c30676bb0c58249ff42f942765f88793b41fdce/multidict-6.7.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:497394b3239fc6f0e13a78a3e1b61296e72bf1c5f94b4c4eb80b265c37a131cd", size = 245528, upload-time = "2026-01-26T02:45:28.991Z" },
+ { url = "https://files.pythonhosted.org/packages/64/f2/6e1107d226278c876c783056b7db43d800bb64c6131cec9c8dfb6903698e/multidict-6.7.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:233b398c29d3f1b9676b4b6f75c518a06fcb2ea0b925119fb2c1bc35c05e1601", size = 258784, upload-time = "2026-01-26T02:45:30.503Z" },
+ { url = "https://files.pythonhosted.org/packages/4d/c1/11f664f14d525e4a1b5327a82d4de61a1db604ab34c6603bb3c2cc63ad34/multidict-6.7.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:93b1818e4a6e0930454f0f2af7dfce69307ca03cdcfb3739bf4d91241967b6c1", size = 251980, upload-time = "2026-01-26T02:45:32.603Z" },
+ { url = "https://files.pythonhosted.org/packages/e1/9f/75a9ac888121d0c5bbd4ecf4eead45668b1766f6baabfb3b7f66a410e231/multidict-6.7.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f33dc2a3abe9249ea5d8360f969ec7f4142e7ac45ee7014d8f8d5acddf178b7b", size = 243602, upload-time = "2026-01-26T02:45:34.043Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/e7/50bf7b004cc8525d80dbbbedfdc7aed3e4c323810890be4413e589074032/multidict-6.7.1-cp314-cp314-win32.whl", hash = "sha256:3ab8b9d8b75aef9df299595d5388b14530839f6422333357af1339443cff777d", size = 40930, upload-time = "2026-01-26T02:45:36.278Z" },
+ { url = "https://files.pythonhosted.org/packages/e0/bf/52f25716bbe93745595800f36fb17b73711f14da59ed0bb2eba141bc9f0f/multidict-6.7.1-cp314-cp314-win_amd64.whl", hash = "sha256:5e01429a929600e7dab7b166062d9bb54a5eed752384c7384c968c2afab8f50f", size = 45074, upload-time = "2026-01-26T02:45:37.546Z" },
+ { url = "https://files.pythonhosted.org/packages/97/ab/22803b03285fa3a525f48217963da3a65ae40f6a1b6f6cf2768879e208f9/multidict-6.7.1-cp314-cp314-win_arm64.whl", hash = "sha256:4885cb0e817aef5d00a2e8451d4665c1808378dc27c2705f1bf4ef8505c0d2e5", size = 42471, upload-time = "2026-01-26T02:45:38.889Z" },
+ { url = "https://files.pythonhosted.org/packages/e0/6d/f9293baa6146ba9507e360ea0292b6422b016907c393e2f63fc40ab7b7b5/multidict-6.7.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:0458c978acd8e6ea53c81eefaddbbee9c6c5e591f41b3f5e8e194780fe026581", size = 82401, upload-time = "2026-01-26T02:45:40.254Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/68/53b5494738d83558d87c3c71a486504d8373421c3e0dbb6d0db48ad42ee0/multidict-6.7.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:c0abd12629b0af3cf590982c0b413b1e7395cd4ec026f30986818ab95bfaa94a", size = 48143, upload-time = "2026-01-26T02:45:41.635Z" },
+ { url = "https://files.pythonhosted.org/packages/37/e8/5284c53310dcdc99ce5d66563f6e5773531a9b9fe9ec7a615e9bc306b05f/multidict-6.7.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:14525a5f61d7d0c94b368a42cff4c9a4e7ba2d52e2672a7b23d84dc86fb02b0c", size = 46507, upload-time = "2026-01-26T02:45:42.99Z" },
+ { url = "https://files.pythonhosted.org/packages/e4/fc/6800d0e5b3875568b4083ecf5f310dcf91d86d52573160834fb4bfcf5e4f/multidict-6.7.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:17307b22c217b4cf05033dabefe68255a534d637c6c9b0cc8382718f87be4262", size = 239358, upload-time = "2026-01-26T02:45:44.376Z" },
+ { url = "https://files.pythonhosted.org/packages/41/75/4ad0973179361cdf3a113905e6e088173198349131be2b390f9fa4da5fc6/multidict-6.7.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7a7e590ff876a3eaf1c02a4dfe0724b6e69a9e9de6d8f556816f29c496046e59", size = 246884, upload-time = "2026-01-26T02:45:47.167Z" },
+ { url = "https://files.pythonhosted.org/packages/c3/9c/095bb28b5da139bd41fb9a5d5caff412584f377914bd8787c2aa98717130/multidict-6.7.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5fa6a95dfee63893d80a34758cd0e0c118a30b8dcb46372bf75106c591b77889", size = 225878, upload-time = "2026-01-26T02:45:48.698Z" },
+ { url = "https://files.pythonhosted.org/packages/07/d0/c0a72000243756e8f5a277b6b514fa005f2c73d481b7d9e47cd4568aa2e4/multidict-6.7.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a0543217a6a017692aa6ae5cc39adb75e587af0f3a82288b1492eb73dd6cc2a4", size = 253542, upload-time = "2026-01-26T02:45:50.164Z" },
+ { url = "https://files.pythonhosted.org/packages/c0/6b/f69da15289e384ecf2a68837ec8b5ad8c33e973aa18b266f50fe55f24b8c/multidict-6.7.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f99fe611c312b3c1c0ace793f92464d8cd263cc3b26b5721950d977b006b6c4d", size = 252403, upload-time = "2026-01-26T02:45:51.779Z" },
+ { url = "https://files.pythonhosted.org/packages/a2/76/b9669547afa5a1a25cd93eaca91c0da1c095b06b6d2d8ec25b713588d3a1/multidict-6.7.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9004d8386d133b7e6135679424c91b0b854d2d164af6ea3f289f8f2761064609", size = 244889, upload-time = "2026-01-26T02:45:53.27Z" },
+ { url = "https://files.pythonhosted.org/packages/7e/a9/a50d2669e506dad33cfc45b5d574a205587b7b8a5f426f2fbb2e90882588/multidict-6.7.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e628ef0e6859ffd8273c69412a2465c4be4a9517d07261b33334b5ec6f3c7489", size = 241982, upload-time = "2026-01-26T02:45:54.919Z" },
+ { url = "https://files.pythonhosted.org/packages/c5/bb/1609558ad8b456b4827d3c5a5b775c93b87878fd3117ed3db3423dfbce1b/multidict-6.7.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:841189848ba629c3552035a6a7f5bf3b02eb304e9fea7492ca220a8eda6b0e5c", size = 232415, upload-time = "2026-01-26T02:45:56.981Z" },
+ { url = "https://files.pythonhosted.org/packages/d8/59/6f61039d2aa9261871e03ab9dc058a550d240f25859b05b67fd70f80d4b3/multidict-6.7.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:ce1bbd7d780bb5a0da032e095c951f7014d6b0a205f8318308140f1a6aba159e", size = 240337, upload-time = "2026-01-26T02:45:58.698Z" },
+ { url = "https://files.pythonhosted.org/packages/a1/29/fdc6a43c203890dc2ae9249971ecd0c41deaedfe00d25cb6564b2edd99eb/multidict-6.7.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b26684587228afed0d50cf804cc71062cc9c1cdf55051c4c6345d372947b268c", size = 248788, upload-time = "2026-01-26T02:46:00.862Z" },
+ { url = "https://files.pythonhosted.org/packages/a9/14/a153a06101323e4cf086ecee3faadba52ff71633d471f9685c42e3736163/multidict-6.7.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:9f9af11306994335398293f9958071019e3ab95e9a707dc1383a35613f6abcb9", size = 242842, upload-time = "2026-01-26T02:46:02.824Z" },
+ { url = "https://files.pythonhosted.org/packages/41/5f/604ae839e64a4a6efc80db94465348d3b328ee955e37acb24badbcd24d83/multidict-6.7.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b4938326284c4f1224178a560987b6cf8b4d38458b113d9b8c1db1a836e640a2", size = 240237, upload-time = "2026-01-26T02:46:05.898Z" },
+ { url = "https://files.pythonhosted.org/packages/5f/60/c3a5187bf66f6fb546ff4ab8fb5a077cbdd832d7b1908d4365c7f74a1917/multidict-6.7.1-cp314-cp314t-win32.whl", hash = "sha256:98655c737850c064a65e006a3df7c997cd3b220be4ec8fe26215760b9697d4d7", size = 48008, upload-time = "2026-01-26T02:46:07.468Z" },
+ { url = "https://files.pythonhosted.org/packages/0c/f7/addf1087b860ac60e6f382240f64fb99f8bfb532bb06f7c542b83c29ca61/multidict-6.7.1-cp314-cp314t-win_amd64.whl", hash = "sha256:497bde6223c212ba11d462853cfa4f0ae6ef97465033e7dc9940cdb3ab5b48e5", size = 53542, upload-time = "2026-01-26T02:46:08.809Z" },
+ { url = "https://files.pythonhosted.org/packages/4c/81/4629d0aa32302ef7b2ec65c75a728cc5ff4fa410c50096174c1632e70b3e/multidict-6.7.1-cp314-cp314t-win_arm64.whl", hash = "sha256:2bbd113e0d4af5db41d5ebfe9ccaff89de2120578164f86a5d17d5a576d1e5b2", size = 44719, upload-time = "2026-01-26T02:46:11.146Z" },
+ { url = "https://files.pythonhosted.org/packages/81/08/7036c080d7117f28a4af526d794aab6a84463126db031b007717c1a6676e/multidict-6.7.1-py3-none-any.whl", hash = "sha256:55d97cc6dae627efa6a6e548885712d4864b81110ac76fa4e534c03819fa4a56", size = 12319, upload-time = "2026-01-26T02:46:44.004Z" },
+]
+
+[[package]]
+name = "openai"
+version = "2.16.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "anyio" },
+ { name = "distro" },
+ { name = "httpx" },
+ { name = "jiter" },
+ { name = "pydantic" },
+ { name = "sniffio" },
+ { name = "tqdm" },
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/b1/6c/e4c964fcf1d527fdf4739e7cc940c60075a4114d50d03871d5d5b1e13a88/openai-2.16.0.tar.gz", hash = "sha256:42eaa22ca0d8ded4367a77374104d7a2feafee5bd60a107c3c11b5243a11cd12", size = 629649, upload-time = "2026-01-27T23:28:02.579Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/16/83/0315bf2cfd75a2ce8a7e54188e9456c60cec6c0cf66728ed07bd9859ff26/openai-2.16.0-py3-none-any.whl", hash = "sha256:5f46643a8f42899a84e80c38838135d7038e7718333ce61396994f887b09a59b", size = 1068612, upload-time = "2026-01-27T23:28:00.356Z" },
+]
+
+[[package]]
+name = "orjson"
+version = "3.11.7"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/53/45/b268004f745ede84e5798b48ee12b05129d19235d0e15267aa57dcdb400b/orjson-3.11.7.tar.gz", hash = "sha256:9b1a67243945819ce55d24a30b59d6a168e86220452d2c96f4d1f093e71c0c49", size = 6144992, upload-time = "2026-02-02T15:38:49.29Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/37/02/da6cb01fc6087048d7f61522c327edf4250f1683a58a839fdcc435746dd5/orjson-3.11.7-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9487abc2c2086e7c8eb9a211d2ce8855bae0e92586279d0d27b341d5ad76c85c", size = 228664, upload-time = "2026-02-02T15:37:25.542Z" },
+ { url = "https://files.pythonhosted.org/packages/c1/c2/5885e7a5881dba9a9af51bc564e8967225a642b3e03d089289a35054e749/orjson-3.11.7-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:79cacb0b52f6004caf92405a7e1f11e6e2de8bdf9019e4f76b44ba045125cd6b", size = 125344, upload-time = "2026-02-02T15:37:26.92Z" },
+ { url = "https://files.pythonhosted.org/packages/a4/1d/4e7688de0a92d1caf600dfd5fb70b4c5bfff51dfa61ac555072ef2d0d32a/orjson-3.11.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2e85fe4698b6a56d5e2ebf7ae87544d668eb6bde1ad1226c13f44663f20ec9e", size = 128404, upload-time = "2026-02-02T15:37:28.108Z" },
+ { url = "https://files.pythonhosted.org/packages/2f/b2/ec04b74ae03a125db7bd69cffd014b227b7f341e3261bf75b5eb88a1aa92/orjson-3.11.7-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b8d14b71c0b12963fe8a62aac87119f1afdf4cb88a400f61ca5ae581449efcb5", size = 123677, upload-time = "2026-02-02T15:37:30.287Z" },
+ { url = "https://files.pythonhosted.org/packages/4c/69/f95bdf960605f08f827f6e3291fe243d8aa9c5c9ff017a8d7232209184c3/orjson-3.11.7-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91c81ef070c8f3220054115e1ef468b1c9ce8497b4e526cb9f68ab4dc0a7ac62", size = 128950, upload-time = "2026-02-02T15:37:31.595Z" },
+ { url = "https://files.pythonhosted.org/packages/a4/1b/de59c57bae1d148ef298852abd31909ac3089cff370dfd4cd84cc99cbc42/orjson-3.11.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:411ebaf34d735e25e358a6d9e7978954a9c9d58cfb47bc6683cdc3964cd2f910", size = 141756, upload-time = "2026-02-02T15:37:32.985Z" },
+ { url = "https://files.pythonhosted.org/packages/ee/9e/9decc59f4499f695f65c650f6cfa6cd4c37a3fbe8fa235a0a3614cb54386/orjson-3.11.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a16bcd08ab0bcdfc7e8801d9c4a9cc17e58418e4d48ddc6ded4e9e4b1a94062b", size = 130812, upload-time = "2026-02-02T15:37:34.204Z" },
+ { url = "https://files.pythonhosted.org/packages/28/e6/59f932bcabd1eac44e334fe8e3281a92eacfcb450586e1f4bde0423728d8/orjson-3.11.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c0b51672e466fd7e56230ffbae7f1639e18d0ce023351fb75da21b71bc2c960", size = 133444, upload-time = "2026-02-02T15:37:35.446Z" },
+ { url = "https://files.pythonhosted.org/packages/f1/36/b0f05c0eaa7ca30bc965e37e6a2956b0d67adb87a9872942d3568da846ae/orjson-3.11.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:136dcd6a2e796dfd9ffca9fc027d778567b0b7c9968d092842d3c323cef88aa8", size = 138609, upload-time = "2026-02-02T15:37:36.657Z" },
+ { url = "https://files.pythonhosted.org/packages/b8/03/58ec7d302b8d86944c60c7b4b82975d5161fcce4c9bc8c6cb1d6741b6115/orjson-3.11.7-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:7ba61079379b0ae29e117db13bda5f28d939766e410d321ec1624afc6a0b0504", size = 408918, upload-time = "2026-02-02T15:37:38.076Z" },
+ { url = "https://files.pythonhosted.org/packages/06/3a/868d65ef9a8b99be723bd510de491349618abd9f62c826cf206d962db295/orjson-3.11.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0527a4510c300e3b406591b0ba69b5dc50031895b0a93743526a3fc45f59d26e", size = 143998, upload-time = "2026-02-02T15:37:39.706Z" },
+ { url = "https://files.pythonhosted.org/packages/5b/c7/1e18e1c83afe3349f4f6dc9e14910f0ae5f82eac756d1412ea4018938535/orjson-3.11.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a709e881723c9b18acddcfb8ba357322491ad553e277cf467e1e7e20e2d90561", size = 134802, upload-time = "2026-02-02T15:37:41.002Z" },
+ { url = "https://files.pythonhosted.org/packages/d4/0b/ccb7ee1a65b37e8eeb8b267dc953561d72370e85185e459616d4345bab34/orjson-3.11.7-cp311-cp311-win32.whl", hash = "sha256:c43b8b5bab288b6b90dac410cca7e986a4fa747a2e8f94615aea407da706980d", size = 127828, upload-time = "2026-02-02T15:37:42.241Z" },
+ { url = "https://files.pythonhosted.org/packages/af/9e/55c776dffda3f381e0f07d010a4f5f3902bf48eaba1bb7684d301acd4924/orjson-3.11.7-cp311-cp311-win_amd64.whl", hash = "sha256:6543001328aa857187f905308a028935864aefe9968af3848401b6fe80dbb471", size = 124941, upload-time = "2026-02-02T15:37:43.444Z" },
+ { url = "https://files.pythonhosted.org/packages/aa/8e/424a620fa7d263b880162505fb107ef5e0afaa765b5b06a88312ac291560/orjson-3.11.7-cp311-cp311-win_arm64.whl", hash = "sha256:1ee5cc7160a821dfe14f130bc8e63e7611051f964b463d9e2a3a573204446a4d", size = 126245, upload-time = "2026-02-02T15:37:45.18Z" },
+ { url = "https://files.pythonhosted.org/packages/80/bf/76f4f1665f6983385938f0e2a5d7efa12a58171b8456c252f3bae8a4cf75/orjson-3.11.7-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:bd03ea7606833655048dab1a00734a2875e3e86c276e1d772b2a02556f0d895f", size = 228545, upload-time = "2026-02-02T15:37:46.376Z" },
+ { url = "https://files.pythonhosted.org/packages/79/53/6c72c002cb13b5a978a068add59b25a8bdf2800ac1c9c8ecdb26d6d97064/orjson-3.11.7-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:89e440ebc74ce8ab5c7bc4ce6757b4a6b1041becb127df818f6997b5c71aa60b", size = 125224, upload-time = "2026-02-02T15:37:47.697Z" },
+ { url = "https://files.pythonhosted.org/packages/2c/83/10e48852865e5dd151bdfe652c06f7da484578ed02c5fca938e3632cb0b8/orjson-3.11.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ede977b5fe5ac91b1dffc0a517ca4542d2ec8a6a4ff7b2652d94f640796342a", size = 128154, upload-time = "2026-02-02T15:37:48.954Z" },
+ { url = "https://files.pythonhosted.org/packages/6e/52/a66e22a2b9abaa374b4a081d410edab6d1e30024707b87eab7c734afe28d/orjson-3.11.7-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b7b1dae39230a393df353827c855a5f176271c23434cfd2db74e0e424e693e10", size = 123548, upload-time = "2026-02-02T15:37:50.187Z" },
+ { url = "https://files.pythonhosted.org/packages/de/38/605d371417021359f4910c496f764c48ceb8997605f8c25bf1dfe58c0ebe/orjson-3.11.7-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed46f17096e28fb28d2975834836a639af7278aa87c84f68ab08fbe5b8bd75fa", size = 129000, upload-time = "2026-02-02T15:37:51.426Z" },
+ { url = "https://files.pythonhosted.org/packages/44/98/af32e842b0ffd2335c89714d48ca4e3917b42f5d6ee5537832e069a4b3ac/orjson-3.11.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3726be79e36e526e3d9c1aceaadbfb4a04ee80a72ab47b3f3c17fefb9812e7b8", size = 141686, upload-time = "2026-02-02T15:37:52.607Z" },
+ { url = "https://files.pythonhosted.org/packages/96/0b/fc793858dfa54be6feee940c1463370ece34b3c39c1ca0aa3845f5ba9892/orjson-3.11.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0724e265bc548af1dedebd9cb3d24b4e1c1e685a343be43e87ba922a5c5fff2f", size = 130812, upload-time = "2026-02-02T15:37:53.944Z" },
+ { url = "https://files.pythonhosted.org/packages/dc/91/98a52415059db3f374757d0b7f0f16e3b5cd5976c90d1c2b56acaea039e6/orjson-3.11.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7745312efa9e11c17fbd3cb3097262d079da26930ae9ae7ba28fb738367cbad", size = 133440, upload-time = "2026-02-02T15:37:55.615Z" },
+ { url = "https://files.pythonhosted.org/packages/dc/b6/cb540117bda61791f46381f8c26c8f93e802892830a6055748d3bb1925ab/orjson-3.11.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f904c24bdeabd4298f7a977ef14ca2a022ca921ed670b92ecd16ab6f3d01f867", size = 138386, upload-time = "2026-02-02T15:37:56.814Z" },
+ { url = "https://files.pythonhosted.org/packages/63/1a/50a3201c334a7f17c231eee5f841342190723794e3b06293f26e7cf87d31/orjson-3.11.7-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:b9fc4d0f81f394689e0814617aadc4f2ea0e8025f38c226cbf22d3b5ddbf025d", size = 408853, upload-time = "2026-02-02T15:37:58.291Z" },
+ { url = "https://files.pythonhosted.org/packages/87/cd/8de1c67d0be44fdc22701e5989c0d015a2adf391498ad42c4dc589cd3013/orjson-3.11.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:849e38203e5be40b776ed2718e587faf204d184fc9a008ae441f9442320c0cab", size = 144130, upload-time = "2026-02-02T15:38:00.163Z" },
+ { url = "https://files.pythonhosted.org/packages/0f/fe/d605d700c35dd55f51710d159fc54516a280923cd1b7e47508982fbb387d/orjson-3.11.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4682d1db3bcebd2b64757e0ddf9e87ae5f00d29d16c5cdf3a62f561d08cc3dd2", size = 134818, upload-time = "2026-02-02T15:38:01.507Z" },
+ { url = "https://files.pythonhosted.org/packages/e4/e4/15ecc67edb3ddb3e2f46ae04475f2d294e8b60c1825fbe28a428b93b3fbd/orjson-3.11.7-cp312-cp312-win32.whl", hash = "sha256:f4f7c956b5215d949a1f65334cf9d7612dde38f20a95f2315deef167def91a6f", size = 127923, upload-time = "2026-02-02T15:38:02.75Z" },
+ { url = "https://files.pythonhosted.org/packages/34/70/2e0855361f76198a3965273048c8e50a9695d88cd75811a5b46444895845/orjson-3.11.7-cp312-cp312-win_amd64.whl", hash = "sha256:bf742e149121dc5648ba0a08ea0871e87b660467ef168a3a5e53bc1fbd64bb74", size = 125007, upload-time = "2026-02-02T15:38:04.032Z" },
+ { url = "https://files.pythonhosted.org/packages/68/40/c2051bd19fc467610fed469dc29e43ac65891571138f476834ca192bc290/orjson-3.11.7-cp312-cp312-win_arm64.whl", hash = "sha256:26c3b9132f783b7d7903bf1efb095fed8d4a3a85ec0d334ee8beff3d7a4749d5", size = 126089, upload-time = "2026-02-02T15:38:05.297Z" },
+ { url = "https://files.pythonhosted.org/packages/89/25/6e0e52cac5aab51d7b6dcd257e855e1dec1c2060f6b28566c509b4665f62/orjson-3.11.7-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:1d98b30cc1313d52d4af17d9c3d307b08389752ec5f2e5febdfada70b0f8c733", size = 228390, upload-time = "2026-02-02T15:38:06.8Z" },
+ { url = "https://files.pythonhosted.org/packages/a5/29/a77f48d2fc8a05bbc529e5ff481fb43d914f9e383ea2469d4f3d51df3d00/orjson-3.11.7-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:d897e81f8d0cbd2abb82226d1860ad2e1ab3ff16d7b08c96ca00df9d45409ef4", size = 125189, upload-time = "2026-02-02T15:38:08.181Z" },
+ { url = "https://files.pythonhosted.org/packages/89/25/0a16e0729a0e6a1504f9d1a13cdd365f030068aab64cec6958396b9969d7/orjson-3.11.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:814be4b49b228cfc0b3c565acf642dd7d13538f966e3ccde61f4f55be3e20785", size = 128106, upload-time = "2026-02-02T15:38:09.41Z" },
+ { url = "https://files.pythonhosted.org/packages/66/da/a2e505469d60666a05ab373f1a6322eb671cb2ba3a0ccfc7d4bc97196787/orjson-3.11.7-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d06e5c5fed5caedd2e540d62e5b1c25e8c82431b9e577c33537e5fa4aa909539", size = 123363, upload-time = "2026-02-02T15:38:10.73Z" },
+ { url = "https://files.pythonhosted.org/packages/23/bf/ed73f88396ea35c71b38961734ea4a4746f7ca0768bf28fd551d37e48dd0/orjson-3.11.7-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:31c80ce534ac4ea3739c5ee751270646cbc46e45aea7576a38ffec040b4029a1", size = 129007, upload-time = "2026-02-02T15:38:12.138Z" },
+ { url = "https://files.pythonhosted.org/packages/73/3c/b05d80716f0225fc9008fbf8ab22841dcc268a626aa550561743714ce3bf/orjson-3.11.7-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f50979824bde13d32b4320eedd513431c921102796d86be3eee0b58e58a3ecd1", size = 141667, upload-time = "2026-02-02T15:38:13.398Z" },
+ { url = "https://files.pythonhosted.org/packages/61/e8/0be9b0addd9bf86abfc938e97441dcd0375d494594b1c8ad10fe57479617/orjson-3.11.7-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e54f3808e2b6b945078c41aa8d9b5834b28c50843846e97807e5adb75fa9705", size = 130832, upload-time = "2026-02-02T15:38:14.698Z" },
+ { url = "https://files.pythonhosted.org/packages/c9/ec/c68e3b9021a31d9ec15a94931db1410136af862955854ed5dd7e7e4f5bff/orjson-3.11.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a12b80df61aab7b98b490fe9e4879925ba666fccdfcd175252ce4d9035865ace", size = 133373, upload-time = "2026-02-02T15:38:16.109Z" },
+ { url = "https://files.pythonhosted.org/packages/d2/45/f3466739aaafa570cc8e77c6dbb853c48bf56e3b43738020e2661e08b0ac/orjson-3.11.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:996b65230271f1a97026fd0e6a753f51fbc0c335d2ad0c6201f711b0da32693b", size = 138307, upload-time = "2026-02-02T15:38:17.453Z" },
+ { url = "https://files.pythonhosted.org/packages/e1/84/9f7f02288da1ffb31405c1be07657afd1eecbcb4b64ee2817b6fe0f785fa/orjson-3.11.7-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:ab49d4b2a6a1d415ddb9f37a21e02e0d5dbfe10b7870b21bf779fc21e9156157", size = 408695, upload-time = "2026-02-02T15:38:18.831Z" },
+ { url = "https://files.pythonhosted.org/packages/18/07/9dd2f0c0104f1a0295ffbe912bc8d63307a539b900dd9e2c48ef7810d971/orjson-3.11.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:390a1dce0c055ddf8adb6aa94a73b45a4a7d7177b5c584b8d1c1947f2ba60fb3", size = 144099, upload-time = "2026-02-02T15:38:20.28Z" },
+ { url = "https://files.pythonhosted.org/packages/a5/66/857a8e4a3292e1f7b1b202883bcdeb43a91566cf59a93f97c53b44bd6801/orjson-3.11.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1eb80451a9c351a71dfaf5b7ccc13ad065405217726b59fdbeadbcc544f9d223", size = 134806, upload-time = "2026-02-02T15:38:22.186Z" },
+ { url = "https://files.pythonhosted.org/packages/0a/5b/6ebcf3defc1aab3a338ca777214966851e92efb1f30dc7fc8285216e6d1b/orjson-3.11.7-cp313-cp313-win32.whl", hash = "sha256:7477aa6a6ec6139c5cb1cc7b214643592169a5494d200397c7fc95d740d5fcf3", size = 127914, upload-time = "2026-02-02T15:38:23.511Z" },
+ { url = "https://files.pythonhosted.org/packages/00/04/c6f72daca5092e3117840a1b1e88dfc809cc1470cf0734890d0366b684a1/orjson-3.11.7-cp313-cp313-win_amd64.whl", hash = "sha256:b9f95dcdea9d4f805daa9ddf02617a89e484c6985fa03055459f90e87d7a0757", size = 124986, upload-time = "2026-02-02T15:38:24.836Z" },
+ { url = "https://files.pythonhosted.org/packages/03/ba/077a0f6f1085d6b806937246860fafbd5b17f3919c70ee3f3d8d9c713f38/orjson-3.11.7-cp313-cp313-win_arm64.whl", hash = "sha256:800988273a014a0541483dc81021247d7eacb0c845a9d1a34a422bc718f41539", size = 126045, upload-time = "2026-02-02T15:38:26.216Z" },
+ { url = "https://files.pythonhosted.org/packages/e9/1e/745565dca749813db9a093c5ebc4bac1a9475c64d54b95654336ac3ed961/orjson-3.11.7-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:de0a37f21d0d364954ad5de1970491d7fbd0fb1ef7417d4d56a36dc01ba0c0a0", size = 228391, upload-time = "2026-02-02T15:38:27.757Z" },
+ { url = "https://files.pythonhosted.org/packages/46/19/e40f6225da4d3aa0c8dc6e5219c5e87c2063a560fe0d72a88deb59776794/orjson-3.11.7-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:c2428d358d85e8da9d37cba18b8c4047c55222007a84f97156a5b22028dfbfc0", size = 125188, upload-time = "2026-02-02T15:38:29.241Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/7e/c4de2babef2c0817fd1f048fd176aa48c37bec8aef53d2fa932983032cce/orjson-3.11.7-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c4bc6c6ac52cdaa267552544c73e486fecbd710b7ac09bc024d5a78555a22f6", size = 128097, upload-time = "2026-02-02T15:38:30.618Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/74/233d360632bafd2197f217eee7fb9c9d0229eac0c18128aee5b35b0014fe/orjson-3.11.7-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd0d68edd7dfca1b2eca9361a44ac9f24b078de3481003159929a0573f21a6bf", size = 123364, upload-time = "2026-02-02T15:38:32.363Z" },
+ { url = "https://files.pythonhosted.org/packages/79/51/af79504981dd31efe20a9e360eb49c15f06df2b40e7f25a0a52d9ae888e8/orjson-3.11.7-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:623ad1b9548ef63886319c16fa317848e465a21513b31a6ad7b57443c3e0dcf5", size = 129076, upload-time = "2026-02-02T15:38:33.68Z" },
+ { url = "https://files.pythonhosted.org/packages/67/e2/da898eb68b72304f8de05ca6715870d09d603ee98d30a27e8a9629abc64b/orjson-3.11.7-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6e776b998ac37c0396093d10290e60283f59cfe0fc3fccbd0ccc4bd04dd19892", size = 141705, upload-time = "2026-02-02T15:38:34.989Z" },
+ { url = "https://files.pythonhosted.org/packages/c5/89/15364d92acb3d903b029e28d834edb8780c2b97404cbf7929aa6b9abdb24/orjson-3.11.7-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:652c6c3af76716f4a9c290371ba2e390ede06f6603edb277b481daf37f6f464e", size = 130855, upload-time = "2026-02-02T15:38:36.379Z" },
+ { url = "https://files.pythonhosted.org/packages/c2/8b/ecdad52d0b38d4b8f514be603e69ccd5eacf4e7241f972e37e79792212ec/orjson-3.11.7-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a56df3239294ea5964adf074c54bcc4f0ccd21636049a2cf3ca9cf03b5d03cf1", size = 133386, upload-time = "2026-02-02T15:38:37.704Z" },
+ { url = "https://files.pythonhosted.org/packages/b9/0e/45e1dcf10e17d0924b7c9162f87ec7b4ca79e28a0548acf6a71788d3e108/orjson-3.11.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:bda117c4148e81f746655d5a3239ae9bd00cb7bc3ca178b5fc5a5997e9744183", size = 138295, upload-time = "2026-02-02T15:38:39.096Z" },
+ { url = "https://files.pythonhosted.org/packages/63/d7/4d2e8b03561257af0450f2845b91fbd111d7e526ccdf737267108075e0ba/orjson-3.11.7-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:23d6c20517a97a9daf1d48b580fcdc6f0516c6f4b5038823426033690b4d2650", size = 408720, upload-time = "2026-02-02T15:38:40.634Z" },
+ { url = "https://files.pythonhosted.org/packages/78/cf/d45343518282108b29c12a65892445fc51f9319dc3c552ceb51bb5905ed2/orjson-3.11.7-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:8ff206156006da5b847c9304b6308a01e8cdbc8cce824e2779a5ba71c3def141", size = 144152, upload-time = "2026-02-02T15:38:42.262Z" },
+ { url = "https://files.pythonhosted.org/packages/a9/3a/d6001f51a7275aacd342e77b735c71fa04125a3f93c36fee4526bc8c654e/orjson-3.11.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:962d046ee1765f74a1da723f4b33e3b228fe3a48bd307acce5021dfefe0e29b2", size = 134814, upload-time = "2026-02-02T15:38:43.627Z" },
+ { url = "https://files.pythonhosted.org/packages/1d/d3/f19b47ce16820cc2c480f7f1723e17f6d411b3a295c60c8ad3aa9ff1c96a/orjson-3.11.7-cp314-cp314-win32.whl", hash = "sha256:89e13dd3f89f1c38a9c9eba5fbf7cdc2d1feca82f5f290864b4b7a6aac704576", size = 127997, upload-time = "2026-02-02T15:38:45.06Z" },
+ { url = "https://files.pythonhosted.org/packages/12/df/172771902943af54bf661a8d102bdf2e7f932127968080632bda6054b62c/orjson-3.11.7-cp314-cp314-win_amd64.whl", hash = "sha256:845c3e0d8ded9c9271cd79596b9b552448b885b97110f628fb687aee2eed11c1", size = 124985, upload-time = "2026-02-02T15:38:46.388Z" },
+ { url = "https://files.pythonhosted.org/packages/6f/1c/f2a8d8a1b17514660a614ce5f7aac74b934e69f5abc2700cc7ced882a009/orjson-3.11.7-cp314-cp314-win_arm64.whl", hash = "sha256:4a2e9c5be347b937a2e0203866f12bba36082e89b402ddb9e927d5822e43088d", size = 126038, upload-time = "2026-02-02T15:38:47.703Z" },
+]
+
+[[package]]
+name = "ormsgpack"
+version = "1.12.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/12/0c/f1761e21486942ab9bb6feaebc610fa074f7c5e496e6962dea5873348077/ormsgpack-1.12.2.tar.gz", hash = "sha256:944a2233640273bee67521795a73cf1e959538e0dfb7ac635505010455e53b33", size = 39031, upload-time = "2026-01-18T20:55:28.023Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/4b/08/8b68f24b18e69d92238aa8f258218e6dfeacf4381d9d07ab8df303f524a9/ormsgpack-1.12.2-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:bd5f4bf04c37888e864f08e740c5a573c4017f6fd6e99fa944c5c935fabf2dd9", size = 378266, upload-time = "2026-01-18T20:55:59.876Z" },
+ { url = "https://files.pythonhosted.org/packages/0d/24/29fc13044ecb7c153523ae0a1972269fcd613650d1fa1a9cec1044c6b666/ormsgpack-1.12.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34d5b28b3570e9fed9a5a76528fc7230c3c76333bc214798958e58e9b79cc18a", size = 203035, upload-time = "2026-01-18T20:55:30.59Z" },
+ { url = "https://files.pythonhosted.org/packages/ad/c2/00169fb25dd8f9213f5e8a549dfb73e4d592009ebc85fbbcd3e1dcac575b/ormsgpack-1.12.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3708693412c28f3538fb5a65da93787b6bbab3484f6bc6e935bfb77a62400ae5", size = 210539, upload-time = "2026-01-18T20:55:48.569Z" },
+ { url = "https://files.pythonhosted.org/packages/1b/33/543627f323ff3c73091f51d6a20db28a1a33531af30873ea90c5ac95a9b5/ormsgpack-1.12.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43013a3f3e2e902e1d05e72c0f1aeb5bedbb8e09240b51e26792a3c89267e181", size = 212401, upload-time = "2026-01-18T20:56:10.101Z" },
+ { url = "https://files.pythonhosted.org/packages/e8/5d/f70e2c3da414f46186659d24745483757bcc9adccb481a6eb93e2b729301/ormsgpack-1.12.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7c8b1667a72cbba74f0ae7ecf3105a5e01304620ed14528b2cb4320679d2869b", size = 387082, upload-time = "2026-01-18T20:56:12.047Z" },
+ { url = "https://files.pythonhosted.org/packages/c0/d6/06e8dc920c7903e051f30934d874d4afccc9bb1c09dcaf0bc03a7de4b343/ormsgpack-1.12.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:df6961442140193e517303d0b5d7bc2e20e69a879c2d774316125350c4a76b92", size = 482346, upload-time = "2026-01-18T20:56:05.152Z" },
+ { url = "https://files.pythonhosted.org/packages/66/c4/f337ac0905eed9c393ef990c54565cd33644918e0a8031fe48c098c71dbf/ormsgpack-1.12.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c6a4c34ddef109647c769d69be65fa1de7a6022b02ad45546a69b3216573eb4a", size = 425181, upload-time = "2026-01-18T20:55:37.83Z" },
+ { url = "https://files.pythonhosted.org/packages/78/29/6d5758fabef3babdf4bbbc453738cc7de9cd3334e4c38dd5737e27b85653/ormsgpack-1.12.2-cp311-cp311-win_amd64.whl", hash = "sha256:73670ed0375ecc303858e3613f407628dd1fca18fe6ac57b7b7ce66cc7bb006c", size = 117182, upload-time = "2026-01-18T20:55:31.472Z" },
+ { url = "https://files.pythonhosted.org/packages/c4/57/17a15549233c37e7fd054c48fe9207492e06b026dbd872b826a0b5f833b6/ormsgpack-1.12.2-cp311-cp311-win_arm64.whl", hash = "sha256:c2be829954434e33601ae5da328cccce3266b098927ca7a30246a0baec2ce7bd", size = 111464, upload-time = "2026-01-18T20:55:38.811Z" },
+ { url = "https://files.pythonhosted.org/packages/4c/36/16c4b1921c308a92cef3bf6663226ae283395aa0ff6e154f925c32e91ff5/ormsgpack-1.12.2-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:7a29d09b64b9694b588ff2f80e9826bdceb3a2b91523c5beae1fab27d5c940e7", size = 378618, upload-time = "2026-01-18T20:55:50.835Z" },
+ { url = "https://files.pythonhosted.org/packages/c0/68/468de634079615abf66ed13bb5c34ff71da237213f29294363beeeca5306/ormsgpack-1.12.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b39e629fd2e1c5b2f46f99778450b59454d1f901bc507963168985e79f09c5d", size = 203186, upload-time = "2026-01-18T20:56:11.163Z" },
+ { url = "https://files.pythonhosted.org/packages/73/a9/d756e01961442688b7939bacd87ce13bfad7d26ce24f910f6028178b2cc8/ormsgpack-1.12.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:958dcb270d30a7cb633a45ee62b9444433fa571a752d2ca484efdac07480876e", size = 210738, upload-time = "2026-01-18T20:56:09.181Z" },
+ { url = "https://files.pythonhosted.org/packages/7b/ba/795b1036888542c9113269a3f5690ab53dd2258c6fb17676ac4bd44fcf94/ormsgpack-1.12.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58d379d72b6c5e964851c77cfedfb386e474adee4fd39791c2c5d9efb53505cc", size = 212569, upload-time = "2026-01-18T20:56:06.135Z" },
+ { url = "https://files.pythonhosted.org/packages/6c/aa/bff73c57497b9e0cba8837c7e4bcab584b1a6dbc91a5dd5526784a5030c8/ormsgpack-1.12.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8463a3fc5f09832e67bdb0e2fda6d518dc4281b133166146a67f54c08496442e", size = 387166, upload-time = "2026-01-18T20:55:36.738Z" },
+ { url = "https://files.pythonhosted.org/packages/d3/cf/f8283cba44bcb7b14f97b6274d449db276b3a86589bdb363169b51bc12de/ormsgpack-1.12.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:eddffb77eff0bad4e67547d67a130604e7e2dfbb7b0cde0796045be4090f35c6", size = 482498, upload-time = "2026-01-18T20:55:29.626Z" },
+ { url = "https://files.pythonhosted.org/packages/05/be/71e37b852d723dfcbe952ad04178c030df60d6b78eba26bfd14c9a40575e/ormsgpack-1.12.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fcd55e5f6ba0dbce624942adf9f152062135f991a0126064889f68eb850de0dd", size = 425518, upload-time = "2026-01-18T20:55:49.556Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/0c/9803aa883d18c7ef197213cd2cbf73ba76472a11fe100fb7dab2884edf48/ormsgpack-1.12.2-cp312-cp312-win_amd64.whl", hash = "sha256:d024b40828f1dde5654faebd0d824f9cc29ad46891f626272dd5bfd7af2333a4", size = 117462, upload-time = "2026-01-18T20:55:47.726Z" },
+ { url = "https://files.pythonhosted.org/packages/c8/9e/029e898298b2cc662f10d7a15652a53e3b525b1e7f07e21fef8536a09bb8/ormsgpack-1.12.2-cp312-cp312-win_arm64.whl", hash = "sha256:da538c542bac7d1c8f3f2a937863dba36f013108ce63e55745941dda4b75dbb6", size = 111559, upload-time = "2026-01-18T20:55:54.273Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/29/bb0eba3288c0449efbb013e9c6f58aea79cf5cb9ee1921f8865f04c1a9d7/ormsgpack-1.12.2-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:5ea60cb5f210b1cfbad8c002948d73447508e629ec375acb82910e3efa8ff355", size = 378661, upload-time = "2026-01-18T20:55:57.765Z" },
+ { url = "https://files.pythonhosted.org/packages/6e/31/5efa31346affdac489acade2926989e019e8ca98129658a183e3add7af5e/ormsgpack-1.12.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3601f19afdbea273ed70b06495e5794606a8b690a568d6c996a90d7255e51c1", size = 203194, upload-time = "2026-01-18T20:56:08.252Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/56/d0087278beef833187e0167f8527235ebe6f6ffc2a143e9de12a98b1ce87/ormsgpack-1.12.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:29a9f17a3dac6054c0dce7925e0f4995c727f7c41859adf9b5572180f640d172", size = 210778, upload-time = "2026-01-18T20:55:17.694Z" },
+ { url = "https://files.pythonhosted.org/packages/1c/a2/072343e1413d9443e5a252a8eb591c2d5b1bffbe5e7bfc78c069361b92eb/ormsgpack-1.12.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39c1bd2092880e413902910388be8715f70b9f15f20779d44e673033a6146f2d", size = 212592, upload-time = "2026-01-18T20:55:32.747Z" },
+ { url = "https://files.pythonhosted.org/packages/a2/8b/a0da3b98a91d41187a63b02dda14267eefc2a74fcb43cc2701066cf1510e/ormsgpack-1.12.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:50b7249244382209877deedeee838aef1542f3d0fc28b8fe71ca9d7e1896a0d7", size = 387164, upload-time = "2026-01-18T20:55:40.853Z" },
+ { url = "https://files.pythonhosted.org/packages/19/bb/6d226bc4cf9fc20d8eb1d976d027a3f7c3491e8f08289a2e76abe96a65f3/ormsgpack-1.12.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:5af04800d844451cf102a59c74a841324868d3f1625c296a06cc655c542a6685", size = 482516, upload-time = "2026-01-18T20:55:42.033Z" },
+ { url = "https://files.pythonhosted.org/packages/fb/f1/bb2c7223398543dedb3dbf8bb93aaa737b387de61c5feaad6f908841b782/ormsgpack-1.12.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cec70477d4371cd524534cd16472d8b9cc187e0e3043a8790545a9a9b296c258", size = 425539, upload-time = "2026-01-18T20:55:24.727Z" },
+ { url = "https://files.pythonhosted.org/packages/7b/e8/0fb45f57a2ada1fed374f7494c8cd55e2f88ccd0ab0a669aa3468716bf5f/ormsgpack-1.12.2-cp313-cp313-win_amd64.whl", hash = "sha256:21f4276caca5c03a818041d637e4019bc84f9d6ca8baa5ea03e5cc8bf56140e9", size = 117459, upload-time = "2026-01-18T20:55:56.876Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/d4/0cfeea1e960d550a131001a7f38a5132c7ae3ebde4c82af1f364ccc5d904/ormsgpack-1.12.2-cp313-cp313-win_arm64.whl", hash = "sha256:baca4b6773d20a82e36d6fd25f341064244f9f86a13dead95dd7d7f996f51709", size = 111577, upload-time = "2026-01-18T20:55:43.605Z" },
+ { url = "https://files.pythonhosted.org/packages/94/16/24d18851334be09c25e87f74307c84950f18c324a4d3c0b41dabdbf19c29/ormsgpack-1.12.2-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:bc68dd5915f4acf66ff2010ee47c8906dc1cf07399b16f4089f8c71733f6e36c", size = 378717, upload-time = "2026-01-18T20:55:26.164Z" },
+ { url = "https://files.pythonhosted.org/packages/b5/a2/88b9b56f83adae8032ac6a6fa7f080c65b3baf9b6b64fd3d37bd202991d4/ormsgpack-1.12.2-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46d084427b4132553940070ad95107266656cb646ea9da4975f85cb1a6676553", size = 203183, upload-time = "2026-01-18T20:55:18.815Z" },
+ { url = "https://files.pythonhosted.org/packages/a9/80/43e4555963bf602e5bdc79cbc8debd8b6d5456c00d2504df9775e74b450b/ormsgpack-1.12.2-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c010da16235806cf1d7bc4c96bf286bfa91c686853395a299b3ddb49499a3e13", size = 210814, upload-time = "2026-01-18T20:55:33.973Z" },
+ { url = "https://files.pythonhosted.org/packages/78/e1/7cfbf28de8bca6efe7e525b329c31277d1b64ce08dcba723971c241a9d60/ormsgpack-1.12.2-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18867233df592c997154ff942a6503df274b5ac1765215bceba7a231bea2745d", size = 212634, upload-time = "2026-01-18T20:55:28.634Z" },
+ { url = "https://files.pythonhosted.org/packages/95/f8/30ae5716e88d792a4e879debee195653c26ddd3964c968594ddef0a3cc7e/ormsgpack-1.12.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b009049086ddc6b8f80c76b3955df1aa22a5fbd7673c525cd63bf91f23122ede", size = 387139, upload-time = "2026-01-18T20:56:02.013Z" },
+ { url = "https://files.pythonhosted.org/packages/dc/81/aee5b18a3e3a0e52f718b37ab4b8af6fae0d9d6a65103036a90c2a8ffb5d/ormsgpack-1.12.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:1dcc17d92b6390d4f18f937cf0b99054824a7815818012ddca925d6e01c2e49e", size = 482578, upload-time = "2026-01-18T20:55:35.117Z" },
+ { url = "https://files.pythonhosted.org/packages/bd/17/71c9ba472d5d45f7546317f467a5fc941929cd68fb32796ca3d13dcbaec2/ormsgpack-1.12.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f04b5e896d510b07c0ad733d7fce2d44b260c5e6c402d272128f8941984e4285", size = 425539, upload-time = "2026-01-18T20:56:04.009Z" },
+ { url = "https://files.pythonhosted.org/packages/2e/a6/ac99cd7fe77e822fed5250ff4b86fa66dd4238937dd178d2299f10b69816/ormsgpack-1.12.2-cp314-cp314-win_amd64.whl", hash = "sha256:ae3aba7eed4ca7cb79fd3436eddd29140f17ea254b91604aa1eb19bfcedb990f", size = 117493, upload-time = "2026-01-18T20:56:07.343Z" },
+ { url = "https://files.pythonhosted.org/packages/3a/67/339872846a1ae4592535385a1c1f93614138566d7af094200c9c3b45d1e5/ormsgpack-1.12.2-cp314-cp314-win_arm64.whl", hash = "sha256:118576ea6006893aea811b17429bfc561b4778fad393f5f538c84af70b01260c", size = 111579, upload-time = "2026-01-18T20:55:21.161Z" },
+ { url = "https://files.pythonhosted.org/packages/49/c2/6feb972dc87285ad381749d3882d8aecbde9f6ecf908dd717d33d66df095/ormsgpack-1.12.2-cp314-cp314t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:7121b3d355d3858781dc40dafe25a32ff8a8242b9d80c692fd548a4b1f7fd3c8", size = 378721, upload-time = "2026-01-18T20:55:52.12Z" },
+ { url = "https://files.pythonhosted.org/packages/a3/9a/900a6b9b413e0f8a471cf07830f9cf65939af039a362204b36bd5b581d8b/ormsgpack-1.12.2-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ee766d2e78251b7a63daf1cddfac36a73562d3ddef68cacfb41b2af64698033", size = 203170, upload-time = "2026-01-18T20:55:44.469Z" },
+ { url = "https://files.pythonhosted.org/packages/87/4c/27a95466354606b256f24fad464d7c97ab62bce6cc529dd4673e1179b8fb/ormsgpack-1.12.2-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:292410a7d23de9b40444636b9b8f1e4e4b814af7f1ef476e44887e52a123f09d", size = 212816, upload-time = "2026-01-18T20:55:23.501Z" },
+ { url = "https://files.pythonhosted.org/packages/73/cd/29cee6007bddf7a834e6cd6f536754c0535fcb939d384f0f37a38b1cddb8/ormsgpack-1.12.2-cp314-cp314t-win_amd64.whl", hash = "sha256:837dd316584485b72ef451d08dd3e96c4a11d12e4963aedb40e08f89685d8ec2", size = 117232, upload-time = "2026-01-18T20:55:45.448Z" },
+]
+
+[[package]]
+name = "packaging"
+version = "26.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/65/ee/299d360cdc32edc7d2cf530f3accf79c4fca01e96ffc950d8a52213bd8e4/packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4", size = 143416, upload-time = "2026-01-21T20:50:39.064Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529", size = 74366, upload-time = "2026-01-21T20:50:37.788Z" },
+]
+
+[[package]]
+name = "pluggy"
+version = "1.6.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
+]
+
+[[package]]
+name = "propcache"
+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/8c/d4/4e2c9aaf7ac2242b9358f98dccd8f90f2605402f5afeff6c578682c2c491/propcache-0.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:60a8fda9644b7dfd5dece8c61d8a85e271cb958075bfc4e01083c148b61a7caf", size = 80208, upload-time = "2025-10-08T19:46:24.597Z" },
+ { url = "https://files.pythonhosted.org/packages/c2/21/d7b68e911f9c8e18e4ae43bdbc1e1e9bbd971f8866eb81608947b6f585ff/propcache-0.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c30b53e7e6bda1d547cabb47c825f3843a0a1a42b0496087bb58d8fedf9f41b5", size = 45777, upload-time = "2025-10-08T19:46:25.733Z" },
+ { url = "https://files.pythonhosted.org/packages/d3/1d/11605e99ac8ea9435651ee71ab4cb4bf03f0949586246476a25aadfec54a/propcache-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6918ecbd897443087a3b7cd978d56546a812517dcaaca51b49526720571fa93e", size = 47647, upload-time = "2025-10-08T19:46:27.304Z" },
+ { url = "https://files.pythonhosted.org/packages/58/1a/3c62c127a8466c9c843bccb503d40a273e5cc69838805f322e2826509e0d/propcache-0.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3d902a36df4e5989763425a8ab9e98cd8ad5c52c823b34ee7ef307fd50582566", size = 214929, upload-time = "2025-10-08T19:46:28.62Z" },
+ { url = "https://files.pythonhosted.org/packages/56/b9/8fa98f850960b367c4b8fe0592e7fc341daa7a9462e925228f10a60cf74f/propcache-0.4.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a9695397f85973bb40427dedddf70d8dc4a44b22f1650dd4af9eedf443d45165", size = 221778, upload-time = "2025-10-08T19:46:30.358Z" },
+ { url = "https://files.pythonhosted.org/packages/46/a6/0ab4f660eb59649d14b3d3d65c439421cf2f87fe5dd68591cbe3c1e78a89/propcache-0.4.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2bb07ffd7eaad486576430c89f9b215f9e4be68c4866a96e97db9e97fead85dc", size = 228144, upload-time = "2025-10-08T19:46:32.607Z" },
+ { url = "https://files.pythonhosted.org/packages/52/6a/57f43e054fb3d3a56ac9fc532bc684fc6169a26c75c353e65425b3e56eef/propcache-0.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd6f30fdcf9ae2a70abd34da54f18da086160e4d7d9251f81f3da0ff84fc5a48", size = 210030, upload-time = "2025-10-08T19:46:33.969Z" },
+ { url = "https://files.pythonhosted.org/packages/40/e2/27e6feebb5f6b8408fa29f5efbb765cd54c153ac77314d27e457a3e993b7/propcache-0.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:fc38cba02d1acba4e2869eef1a57a43dfbd3d49a59bf90dda7444ec2be6a5570", size = 208252, upload-time = "2025-10-08T19:46:35.309Z" },
+ { url = "https://files.pythonhosted.org/packages/9e/f8/91c27b22ccda1dbc7967f921c42825564fa5336a01ecd72eb78a9f4f53c2/propcache-0.4.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:67fad6162281e80e882fb3ec355398cf72864a54069d060321f6cd0ade95fe85", size = 202064, upload-time = "2025-10-08T19:46:36.993Z" },
+ { url = "https://files.pythonhosted.org/packages/f2/26/7f00bd6bd1adba5aafe5f4a66390f243acab58eab24ff1a08bebb2ef9d40/propcache-0.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f10207adf04d08bec185bae14d9606a1444715bc99180f9331c9c02093e1959e", size = 212429, upload-time = "2025-10-08T19:46:38.398Z" },
+ { url = "https://files.pythonhosted.org/packages/84/89/fd108ba7815c1117ddca79c228f3f8a15fc82a73bca8b142eb5de13b2785/propcache-0.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e9b0d8d0845bbc4cfcdcbcdbf5086886bc8157aa963c31c777ceff7846c77757", size = 216727, upload-time = "2025-10-08T19:46:39.732Z" },
+ { url = "https://files.pythonhosted.org/packages/79/37/3ec3f7e3173e73f1d600495d8b545b53802cbf35506e5732dd8578db3724/propcache-0.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:981333cb2f4c1896a12f4ab92a9cc8f09ea664e9b7dbdc4eff74627af3a11c0f", size = 205097, upload-time = "2025-10-08T19:46:41.025Z" },
+ { url = "https://files.pythonhosted.org/packages/61/b0/b2631c19793f869d35f47d5a3a56fb19e9160d3c119f15ac7344fc3ccae7/propcache-0.4.1-cp311-cp311-win32.whl", hash = "sha256:f1d2f90aeec838a52f1c1a32fe9a619fefd5e411721a9117fbf82aea638fe8a1", size = 38084, upload-time = "2025-10-08T19:46:42.693Z" },
+ { url = "https://files.pythonhosted.org/packages/f4/78/6cce448e2098e9f3bfc91bb877f06aa24b6ccace872e39c53b2f707c4648/propcache-0.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:364426a62660f3f699949ac8c621aad6977be7126c5807ce48c0aeb8e7333ea6", size = 41637, upload-time = "2025-10-08T19:46:43.778Z" },
+ { url = "https://files.pythonhosted.org/packages/9c/e9/754f180cccd7f51a39913782c74717c581b9cc8177ad0e949f4d51812383/propcache-0.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:e53f3a38d3510c11953f3e6a33f205c6d1b001129f972805ca9b42fc308bc239", size = 38064, upload-time = "2025-10-08T19:46:44.872Z" },
+ { 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" },
+ { url = "https://files.pythonhosted.org/packages/86/bd/47816020d337f4a746edc42fe8d53669965138f39ee117414c7d7a340cfe/propcache-0.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c80ee5802e3fb9ea37938e7eecc307fb984837091d5fd262bb37238b1ae97641", size = 206981, upload-time = "2025-10-08T19:47:55.715Z" },
+ { url = "https://files.pythonhosted.org/packages/df/f6/c5fa1357cc9748510ee55f37173eb31bfde6d94e98ccd9e6f033f2fc06e1/propcache-0.4.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ed5a841e8bb29a55fb8159ed526b26adc5bdd7e8bd7bf793ce647cb08656cdf4", size = 211490, upload-time = "2025-10-08T19:47:57.499Z" },
+ { url = "https://files.pythonhosted.org/packages/80/1e/e5889652a7c4a3846683401a48f0f2e5083ce0ec1a8a5221d8058fbd1adf/propcache-0.4.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:55c72fd6ea2da4c318e74ffdf93c4fe4e926051133657459131a95c846d16d44", size = 215371, upload-time = "2025-10-08T19:47:59.317Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/f2/889ad4b2408f72fe1a4f6a19491177b30ea7bf1a0fd5f17050ca08cfc882/propcache-0.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8326e144341460402713f91df60ade3c999d601e7eb5ff8f6f7862d54de0610d", size = 201424, upload-time = "2025-10-08T19:48:00.67Z" },
+ { url = "https://files.pythonhosted.org/packages/27/73/033d63069b57b0812c8bd19f311faebeceb6ba31b8f32b73432d12a0b826/propcache-0.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:060b16ae65bc098da7f6d25bf359f1f31f688384858204fe5d652979e0015e5b", size = 197566, upload-time = "2025-10-08T19:48:02.604Z" },
+ { url = "https://files.pythonhosted.org/packages/dc/89/ce24f3dc182630b4e07aa6d15f0ff4b14ed4b9955fae95a0b54c58d66c05/propcache-0.4.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:89eb3fa9524f7bec9de6e83cf3faed9d79bffa560672c118a96a171a6f55831e", size = 193130, upload-time = "2025-10-08T19:48:04.499Z" },
+ { url = "https://files.pythonhosted.org/packages/a9/24/ef0d5fd1a811fb5c609278d0209c9f10c35f20581fcc16f818da959fc5b4/propcache-0.4.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:dee69d7015dc235f526fe80a9c90d65eb0039103fe565776250881731f06349f", size = 202625, upload-time = "2025-10-08T19:48:06.213Z" },
+ { url = "https://files.pythonhosted.org/packages/f5/02/98ec20ff5546f68d673df2f7a69e8c0d076b5abd05ca882dc7ee3a83653d/propcache-0.4.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:5558992a00dfd54ccbc64a32726a3357ec93825a418a401f5cc67df0ac5d9e49", size = 204209, upload-time = "2025-10-08T19:48:08.432Z" },
+ { url = "https://files.pythonhosted.org/packages/a0/87/492694f76759b15f0467a2a93ab68d32859672b646aa8a04ce4864e7932d/propcache-0.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c9b822a577f560fbd9554812526831712c1436d2c046cedee4c3796d3543b144", size = 197797, upload-time = "2025-10-08T19:48:09.968Z" },
+ { url = "https://files.pythonhosted.org/packages/ee/36/66367de3575db1d2d3f3d177432bd14ee577a39d3f5d1b3d5df8afe3b6e2/propcache-0.4.1-cp314-cp314-win32.whl", hash = "sha256:ab4c29b49d560fe48b696cdcb127dd36e0bc2472548f3bf56cc5cb3da2b2984f", size = 38140, upload-time = "2025-10-08T19:48:11.232Z" },
+ { url = "https://files.pythonhosted.org/packages/0c/2a/a758b47de253636e1b8aef181c0b4f4f204bf0dd964914fb2af90a95b49b/propcache-0.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:5a103c3eb905fcea0ab98be99c3a9a5ab2de60228aa5aceedc614c0281cf6153", size = 41257, upload-time = "2025-10-08T19:48:12.707Z" },
+ { url = "https://files.pythonhosted.org/packages/34/5e/63bd5896c3fec12edcbd6f12508d4890d23c265df28c74b175e1ef9f4f3b/propcache-0.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:74c1fb26515153e482e00177a1ad654721bf9207da8a494a0c05e797ad27b992", size = 38097, upload-time = "2025-10-08T19:48:13.923Z" },
+ { url = "https://files.pythonhosted.org/packages/99/85/9ff785d787ccf9bbb3f3106f79884a130951436f58392000231b4c737c80/propcache-0.4.1-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:824e908bce90fb2743bd6b59db36eb4f45cd350a39637c9f73b1c1ea66f5b75f", size = 81455, upload-time = "2025-10-08T19:48:15.16Z" },
+ { url = "https://files.pythonhosted.org/packages/90/85/2431c10c8e7ddb1445c1f7c4b54d886e8ad20e3c6307e7218f05922cad67/propcache-0.4.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:c2b5e7db5328427c57c8e8831abda175421b709672f6cfc3d630c3b7e2146393", size = 46372, upload-time = "2025-10-08T19:48:16.424Z" },
+ { url = "https://files.pythonhosted.org/packages/01/20/b0972d902472da9bcb683fa595099911f4d2e86e5683bcc45de60dd05dc3/propcache-0.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6f6ff873ed40292cd4969ef5310179afd5db59fdf055897e282485043fc80ad0", size = 48411, upload-time = "2025-10-08T19:48:17.577Z" },
+ { url = "https://files.pythonhosted.org/packages/e2/e3/7dc89f4f21e8f99bad3d5ddb3a3389afcf9da4ac69e3deb2dcdc96e74169/propcache-0.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:49a2dc67c154db2c1463013594c458881a069fcf98940e61a0569016a583020a", size = 275712, upload-time = "2025-10-08T19:48:18.901Z" },
+ { url = "https://files.pythonhosted.org/packages/20/67/89800c8352489b21a8047c773067644e3897f02ecbbd610f4d46b7f08612/propcache-0.4.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:005f08e6a0529984491e37d8dbc3dd86f84bd78a8ceb5fa9a021f4c48d4984be", size = 273557, upload-time = "2025-10-08T19:48:20.762Z" },
+ { url = "https://files.pythonhosted.org/packages/e2/a1/b52b055c766a54ce6d9c16d9aca0cad8059acd9637cdf8aa0222f4a026ef/propcache-0.4.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5c3310452e0d31390da9035c348633b43d7e7feb2e37be252be6da45abd1abcc", size = 280015, upload-time = "2025-10-08T19:48:22.592Z" },
+ { url = "https://files.pythonhosted.org/packages/48/c8/33cee30bd890672c63743049f3c9e4be087e6780906bfc3ec58528be59c1/propcache-0.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c3c70630930447f9ef1caac7728c8ad1c56bc5015338b20fed0d08ea2480b3a", size = 262880, upload-time = "2025-10-08T19:48:23.947Z" },
+ { url = "https://files.pythonhosted.org/packages/0c/b1/8f08a143b204b418285c88b83d00edbd61afbc2c6415ffafc8905da7038b/propcache-0.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8e57061305815dfc910a3634dcf584f08168a8836e6999983569f51a8544cd89", size = 260938, upload-time = "2025-10-08T19:48:25.656Z" },
+ { url = "https://files.pythonhosted.org/packages/cf/12/96e4664c82ca2f31e1c8dff86afb867348979eb78d3cb8546a680287a1e9/propcache-0.4.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:521a463429ef54143092c11a77e04056dd00636f72e8c45b70aaa3140d639726", size = 247641, upload-time = "2025-10-08T19:48:27.207Z" },
+ { url = "https://files.pythonhosted.org/packages/18/ed/e7a9cfca28133386ba52278136d42209d3125db08d0a6395f0cba0c0285c/propcache-0.4.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:120c964da3fdc75e3731aa392527136d4ad35868cc556fd09bb6d09172d9a367", size = 262510, upload-time = "2025-10-08T19:48:28.65Z" },
+ { url = "https://files.pythonhosted.org/packages/f5/76/16d8bf65e8845dd62b4e2b57444ab81f07f40caa5652b8969b87ddcf2ef6/propcache-0.4.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:d8f353eb14ee3441ee844ade4277d560cdd68288838673273b978e3d6d2c8f36", size = 263161, upload-time = "2025-10-08T19:48:30.133Z" },
+ { url = "https://files.pythonhosted.org/packages/e7/70/c99e9edb5d91d5ad8a49fa3c1e8285ba64f1476782fed10ab251ff413ba1/propcache-0.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ab2943be7c652f09638800905ee1bab2c544e537edb57d527997a24c13dc1455", size = 257393, upload-time = "2025-10-08T19:48:31.567Z" },
+ { url = "https://files.pythonhosted.org/packages/08/02/87b25304249a35c0915d236575bc3574a323f60b47939a2262b77632a3ee/propcache-0.4.1-cp314-cp314t-win32.whl", hash = "sha256:05674a162469f31358c30bcaa8883cb7829fa3110bf9c0991fe27d7896c42d85", size = 42546, upload-time = "2025-10-08T19:48:32.872Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/ef/3c6ecf8b317aa982f309835e8f96987466123c6e596646d4e6a1dfcd080f/propcache-0.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:990f6b3e2a27d683cb7602ed6c86f15ee6b43b1194736f9baaeb93d0016633b1", size = 46259, upload-time = "2025-10-08T19:48:34.226Z" },
+ { url = "https://files.pythonhosted.org/packages/c4/2d/346e946d4951f37eca1e4f55be0f0174c52cd70720f84029b02f296f4a38/propcache-0.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:ecef2343af4cc68e05131e45024ba34f6095821988a9d0a02aa7c73fcc448aa9", size = 40428, upload-time = "2025-10-08T19:48:35.441Z" },
+ { url = "https://files.pythonhosted.org/packages/5b/5a/bc7b4a4ef808fa59a816c17b20c4bef6884daebbdf627ff2a161da67da19/propcache-0.4.1-py3-none-any.whl", hash = "sha256:af2a6052aeb6cf17d3e46ee169099044fd8224cbaf75c76a2ef596e8163e2237", size = 13305, upload-time = "2025-10-08T19:49:00.792Z" },
+]
+
+[[package]]
+name = "pydantic"
+version = "2.12.5"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "annotated-types" },
+ { name = "pydantic-core" },
+ { name = "typing-extensions" },
+ { name = "typing-inspection" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/69/44/36f1a6e523abc58ae5f928898e4aca2e0ea509b5aa6f6f392a5d882be928/pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49", size = 821591, upload-time = "2025-11-26T15:11:46.471Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d", size = 463580, upload-time = "2025-11-26T15:11:44.605Z" },
+]
+
+[[package]]
+name = "pydantic-core"
+version = "2.41.5"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "typing-extensions" },
+]
+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/e8/72/74a989dd9f2084b3d9530b0915fdda64ac48831c30dbf7c72a41a5232db8/pydantic_core-2.41.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6", size = 2105873, upload-time = "2025-11-04T13:39:31.373Z" },
+ { url = "https://files.pythonhosted.org/packages/12/44/37e403fd9455708b3b942949e1d7febc02167662bf1a7da5b78ee1ea2842/pydantic_core-2.41.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b", size = 1899826, upload-time = "2025-11-04T13:39:32.897Z" },
+ { url = "https://files.pythonhosted.org/packages/33/7f/1d5cab3ccf44c1935a359d51a8a2a9e1a654b744b5e7f80d41b88d501eec/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a", size = 1917869, upload-time = "2025-11-04T13:39:34.469Z" },
+ { url = "https://files.pythonhosted.org/packages/6e/6a/30d94a9674a7fe4f4744052ed6c5e083424510be1e93da5bc47569d11810/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7b576130c69225432866fe2f4a469a85a54ade141d96fd396dffcf607b558f8", size = 2063890, upload-time = "2025-11-04T13:39:36.053Z" },
+ { url = "https://files.pythonhosted.org/packages/50/be/76e5d46203fcb2750e542f32e6c371ffa9b8ad17364cf94bb0818dbfb50c/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6cb58b9c66f7e4179a2d5e0f849c48eff5c1fca560994d6eb6543abf955a149e", size = 2229740, upload-time = "2025-11-04T13:39:37.753Z" },
+ { url = "https://files.pythonhosted.org/packages/d3/ee/fed784df0144793489f87db310a6bbf8118d7b630ed07aa180d6067e653a/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88942d3a3dff3afc8288c21e565e476fc278902ae4d6d134f1eeda118cc830b1", size = 2350021, upload-time = "2025-11-04T13:39:40.94Z" },
+ { url = "https://files.pythonhosted.org/packages/c8/be/8fed28dd0a180dca19e72c233cbf58efa36df055e5b9d90d64fd1740b828/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f31d95a179f8d64d90f6831d71fa93290893a33148d890ba15de25642c5d075b", size = 2066378, upload-time = "2025-11-04T13:39:42.523Z" },
+ { url = "https://files.pythonhosted.org/packages/b0/3b/698cf8ae1d536a010e05121b4958b1257f0b5522085e335360e53a6b1c8b/pydantic_core-2.41.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1df3d34aced70add6f867a8cf413e299177e0c22660cc767218373d0779487b", size = 2175761, upload-time = "2025-11-04T13:39:44.553Z" },
+ { url = "https://files.pythonhosted.org/packages/b8/ba/15d537423939553116dea94ce02f9c31be0fa9d0b806d427e0308ec17145/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4009935984bd36bd2c774e13f9a09563ce8de4abaa7226f5108262fa3e637284", size = 2146303, upload-time = "2025-11-04T13:39:46.238Z" },
+ { url = "https://files.pythonhosted.org/packages/58/7f/0de669bf37d206723795f9c90c82966726a2ab06c336deba4735b55af431/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:34a64bc3441dc1213096a20fe27e8e128bd3ff89921706e83c0b1ac971276594", size = 2340355, upload-time = "2025-11-04T13:39:48.002Z" },
+ { url = "https://files.pythonhosted.org/packages/e5/de/e7482c435b83d7e3c3ee5ee4451f6e8973cff0eb6007d2872ce6383f6398/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c9e19dd6e28fdcaa5a1de679aec4141f691023916427ef9bae8584f9c2fb3b0e", size = 2319875, upload-time = "2025-11-04T13:39:49.705Z" },
+ { url = "https://files.pythonhosted.org/packages/fe/e6/8c9e81bb6dd7560e33b9053351c29f30c8194b72f2d6932888581f503482/pydantic_core-2.41.5-cp311-cp311-win32.whl", hash = "sha256:2c010c6ded393148374c0f6f0bf89d206bf3217f201faa0635dcd56bd1520f6b", size = 1987549, upload-time = "2025-11-04T13:39:51.842Z" },
+ { url = "https://files.pythonhosted.org/packages/11/66/f14d1d978ea94d1bc21fc98fcf570f9542fe55bfcc40269d4e1a21c19bf7/pydantic_core-2.41.5-cp311-cp311-win_amd64.whl", hash = "sha256:76ee27c6e9c7f16f47db7a94157112a2f3a00e958bc626e2f4ee8bec5c328fbe", size = 2011305, upload-time = "2025-11-04T13:39:53.485Z" },
+ { url = "https://files.pythonhosted.org/packages/56/d8/0e271434e8efd03186c5386671328154ee349ff0354d83c74f5caaf096ed/pydantic_core-2.41.5-cp311-cp311-win_arm64.whl", hash = "sha256:4bc36bbc0b7584de96561184ad7f012478987882ebf9f9c389b23f432ea3d90f", size = 1972902, upload-time = "2025-11-04T13:39:56.488Z" },
+ { 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" },
+ { url = "https://files.pythonhosted.org/packages/84/a3/15a82ac7bd97992a82257f777b3583d3e84bdb06ba6858f745daa2ec8a85/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66", size = 2063691, upload-time = "2025-11-04T13:41:03.504Z" },
+ { url = "https://files.pythonhosted.org/packages/74/9b/0046701313c6ef08c0c1cf0e028c67c770a4e1275ca73131563c5f2a310a/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869", size = 2213897, upload-time = "2025-11-04T13:41:05.804Z" },
+ { url = "https://files.pythonhosted.org/packages/8a/cd/6bac76ecd1b27e75a95ca3a9a559c643b3afcd2dd62086d4b7a32a18b169/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2", size = 2333302, upload-time = "2025-11-04T13:41:07.809Z" },
+ { url = "https://files.pythonhosted.org/packages/4c/d2/ef2074dc020dd6e109611a8be4449b98cd25e1b9b8a303c2f0fca2f2bcf7/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375", size = 2064877, upload-time = "2025-11-04T13:41:09.827Z" },
+ { url = "https://files.pythonhosted.org/packages/18/66/e9db17a9a763d72f03de903883c057b2592c09509ccfe468187f2a2eef29/pydantic_core-2.41.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553", size = 2180680, upload-time = "2025-11-04T13:41:12.379Z" },
+ { url = "https://files.pythonhosted.org/packages/d3/9e/3ce66cebb929f3ced22be85d4c2399b8e85b622db77dad36b73c5387f8f8/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90", size = 2138960, upload-time = "2025-11-04T13:41:14.627Z" },
+ { url = "https://files.pythonhosted.org/packages/a6/62/205a998f4327d2079326b01abee48e502ea739d174f0a89295c481a2272e/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07", size = 2339102, upload-time = "2025-11-04T13:41:16.868Z" },
+ { url = "https://files.pythonhosted.org/packages/3c/0d/f05e79471e889d74d3d88f5bd20d0ed189ad94c2423d81ff8d0000aab4ff/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb", size = 2326039, upload-time = "2025-11-04T13:41:18.934Z" },
+ { url = "https://files.pythonhosted.org/packages/ec/e1/e08a6208bb100da7e0c4b288eed624a703f4d129bde2da475721a80cab32/pydantic_core-2.41.5-cp314-cp314-win32.whl", hash = "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23", size = 1995126, upload-time = "2025-11-04T13:41:21.418Z" },
+ { url = "https://files.pythonhosted.org/packages/48/5d/56ba7b24e9557f99c9237e29f5c09913c81eeb2f3217e40e922353668092/pydantic_core-2.41.5-cp314-cp314-win_amd64.whl", hash = "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf", size = 2015489, upload-time = "2025-11-04T13:41:24.076Z" },
+ { url = "https://files.pythonhosted.org/packages/4e/bb/f7a190991ec9e3e0ba22e4993d8755bbc4a32925c0b5b42775c03e8148f9/pydantic_core-2.41.5-cp314-cp314-win_arm64.whl", hash = "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0", size = 1977288, upload-time = "2025-11-04T13:41:26.33Z" },
+ { url = "https://files.pythonhosted.org/packages/92/ed/77542d0c51538e32e15afe7899d79efce4b81eee631d99850edc2f5e9349/pydantic_core-2.41.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a", size = 2120255, upload-time = "2025-11-04T13:41:28.569Z" },
+ { url = "https://files.pythonhosted.org/packages/bb/3d/6913dde84d5be21e284439676168b28d8bbba5600d838b9dca99de0fad71/pydantic_core-2.41.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3", size = 1863760, upload-time = "2025-11-04T13:41:31.055Z" },
+ { url = "https://files.pythonhosted.org/packages/5a/f0/e5e6b99d4191da102f2b0eb9687aaa7f5bea5d9964071a84effc3e40f997/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c", size = 1878092, upload-time = "2025-11-04T13:41:33.21Z" },
+ { url = "https://files.pythonhosted.org/packages/71/48/36fb760642d568925953bcc8116455513d6e34c4beaa37544118c36aba6d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612", size = 2053385, upload-time = "2025-11-04T13:41:35.508Z" },
+ { url = "https://files.pythonhosted.org/packages/20/25/92dc684dd8eb75a234bc1c764b4210cf2646479d54b47bf46061657292a8/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d", size = 2218832, upload-time = "2025-11-04T13:41:37.732Z" },
+ { url = "https://files.pythonhosted.org/packages/e2/09/f53e0b05023d3e30357d82eb35835d0f6340ca344720a4599cd663dca599/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9", size = 2327585, upload-time = "2025-11-04T13:41:40Z" },
+ { url = "https://files.pythonhosted.org/packages/aa/4e/2ae1aa85d6af35a39b236b1b1641de73f5a6ac4d5a7509f77b814885760c/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660", size = 2041078, upload-time = "2025-11-04T13:41:42.323Z" },
+ { url = "https://files.pythonhosted.org/packages/cd/13/2e215f17f0ef326fc72afe94776edb77525142c693767fc347ed6288728d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9", size = 2173914, upload-time = "2025-11-04T13:41:45.221Z" },
+ { url = "https://files.pythonhosted.org/packages/02/7a/f999a6dcbcd0e5660bc348a3991c8915ce6599f4f2c6ac22f01d7a10816c/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3", size = 2129560, upload-time = "2025-11-04T13:41:47.474Z" },
+ { url = "https://files.pythonhosted.org/packages/3a/b1/6c990ac65e3b4c079a4fb9f5b05f5b013afa0f4ed6780a3dd236d2cbdc64/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf", size = 2329244, upload-time = "2025-11-04T13:41:49.992Z" },
+ { url = "https://files.pythonhosted.org/packages/d9/02/3c562f3a51afd4d88fff8dffb1771b30cfdfd79befd9883ee094f5b6c0d8/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470", size = 2331955, upload-time = "2025-11-04T13:41:54.079Z" },
+ { 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/11/72/90fda5ee3b97e51c494938a4a44c3a35a9c96c19bba12372fb9c634d6f57/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034", size = 2115441, upload-time = "2025-11-04T13:42:39.557Z" },
+ { url = "https://files.pythonhosted.org/packages/1f/53/8942f884fa33f50794f119012dc6a1a02ac43a56407adaac20463df8e98f/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c", size = 1930291, upload-time = "2025-11-04T13:42:42.169Z" },
+ { url = "https://files.pythonhosted.org/packages/79/c8/ecb9ed9cd942bce09fc888ee960b52654fbdbede4ba6c2d6e0d3b1d8b49c/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2", size = 1948632, upload-time = "2025-11-04T13:42:44.564Z" },
+ { url = "https://files.pythonhosted.org/packages/2e/1b/687711069de7efa6af934e74f601e2a4307365e8fdc404703afc453eab26/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f15489ba13d61f670dcc96772e733aad1a6f9c429cc27574c6cdaed82d0146ad", size = 2138905, upload-time = "2025-11-04T13:42:47.156Z" },
+ { 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" },
+ { url = "https://files.pythonhosted.org/packages/5f/9b/1b3f0e9f9305839d7e84912f9e8bfbd191ed1b1ef48083609f0dabde978c/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26", size = 2101980, upload-time = "2025-11-04T13:43:25.97Z" },
+ { url = "https://files.pythonhosted.org/packages/a4/ed/d71fefcb4263df0da6a85b5d8a7508360f2f2e9b3bf5814be9c8bccdccc1/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808", size = 1923865, upload-time = "2025-11-04T13:43:28.763Z" },
+ { url = "https://files.pythonhosted.org/packages/ce/3a/626b38db460d675f873e4444b4bb030453bbe7b4ba55df821d026a0493c4/pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc", size = 2134256, upload-time = "2025-11-04T13:43:31.71Z" },
+ { url = "https://files.pythonhosted.org/packages/83/d9/8412d7f06f616bbc053d30cb4e5f76786af3221462ad5eee1f202021eb4e/pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:287dad91cfb551c363dc62899a80e9e14da1f0e2b6ebde82c806612ca2a13ef1", size = 2174762, upload-time = "2025-11-04T13:43:34.744Z" },
+ { url = "https://files.pythonhosted.org/packages/55/4c/162d906b8e3ba3a99354e20faa1b49a85206c47de97a639510a0e673f5da/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:03b77d184b9eb40240ae9fd676ca364ce1085f203e1b1256f8ab9984dca80a84", size = 2143141, upload-time = "2025-11-04T13:43:37.701Z" },
+ { url = "https://files.pythonhosted.org/packages/1f/f2/f11dd73284122713f5f89fc940f370d035fa8e1e078d446b3313955157fe/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:a668ce24de96165bb239160b3d854943128f4334822900534f2fe947930e5770", size = 2330317, upload-time = "2025-11-04T13:43:40.406Z" },
+ { url = "https://files.pythonhosted.org/packages/88/9d/b06ca6acfe4abb296110fb1273a4d848a0bfb2ff65f3ee92127b3244e16b/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f14f8f046c14563f8eb3f45f499cc658ab8d10072961e07225e507adb700e93f", size = 2316992, upload-time = "2025-11-04T13:43:43.602Z" },
+ { url = "https://files.pythonhosted.org/packages/36/c7/cfc8e811f061c841d7990b0201912c3556bfeb99cdcb7ed24adc8d6f8704/pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51", size = 2145302, upload-time = "2025-11-04T13:43:46.64Z" },
+]
+
+[[package]]
+name = "pygments"
+version = "2.19.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" },
+]
+
+[[package]]
+name = "pytest"
+version = "9.0.2"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "iniconfig" },
+ { name = "packaging" },
+ { name = "pluggy" },
+ { name = "pygments" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/d1/db/7ef3487e0fb0049ddb5ce41d3a49c235bf9ad299b6a25d5780a89f19230f/pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11", size = 1568901, upload-time = "2025-12-06T21:30:51.014Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", size = 374801, upload-time = "2025-12-06T21:30:49.154Z" },
+]
+
+[[package]]
+name = "python-dotenv"
+version = "1.2.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f0/26/19cadc79a718c5edbec86fd4919a6b6d3f681039a2f6d66d14be94e75fb9/python_dotenv-1.2.1.tar.gz", hash = "sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6", size = 44221, upload-time = "2025-10-26T15:12:10.434Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/14/1b/a298b06749107c305e1fe0f814c6c74aea7b2f1e10989cb30f544a1b3253/python_dotenv-1.2.1-py3-none-any.whl", hash = "sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61", size = 21230, upload-time = "2025-10-26T15:12:09.109Z" },
+]
+
+[[package]]
+name = "pyyaml"
+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/6d/16/a95b6757765b7b031c9374925bb718d55e0a9ba8a1b6a12d25962ea44347/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e", size = 185826, upload-time = "2025-09-25T21:31:58.655Z" },
+ { url = "https://files.pythonhosted.org/packages/16/19/13de8e4377ed53079ee996e1ab0a9c33ec2faf808a4647b7b4c0d46dd239/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824", size = 175577, upload-time = "2025-09-25T21:32:00.088Z" },
+ { url = "https://files.pythonhosted.org/packages/0c/62/d2eb46264d4b157dae1275b573017abec435397aa59cbcdab6fc978a8af4/pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c", size = 775556, upload-time = "2025-09-25T21:32:01.31Z" },
+ { url = "https://files.pythonhosted.org/packages/10/cb/16c3f2cf3266edd25aaa00d6c4350381c8b012ed6f5276675b9eba8d9ff4/pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00", size = 882114, upload-time = "2025-09-25T21:32:03.376Z" },
+ { url = "https://files.pythonhosted.org/packages/71/60/917329f640924b18ff085ab889a11c763e0b573da888e8404ff486657602/pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d", size = 806638, upload-time = "2025-09-25T21:32:04.553Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/6f/529b0f316a9fd167281a6c3826b5583e6192dba792dd55e3203d3f8e655a/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a", size = 767463, upload-time = "2025-09-25T21:32:06.152Z" },
+ { url = "https://files.pythonhosted.org/packages/f2/6a/b627b4e0c1dd03718543519ffb2f1deea4a1e6d42fbab8021936a4d22589/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4", size = 794986, upload-time = "2025-09-25T21:32:07.367Z" },
+ { url = "https://files.pythonhosted.org/packages/45/91/47a6e1c42d9ee337c4839208f30d9f09caa9f720ec7582917b264defc875/pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b", size = 142543, upload-time = "2025-09-25T21:32:08.95Z" },
+ { url = "https://files.pythonhosted.org/packages/da/e3/ea007450a105ae919a72393cb06f122f288ef60bba2dc64b26e2646fa315/pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf", size = 158763, upload-time = "2025-09-25T21:32:09.96Z" },
+ { 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" },
+ { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" },
+ { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" },
+ { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" },
+ { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" },
+ { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" },
+ { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" },
+ { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" },
+ { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" },
+ { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" },
+ { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" },
+ { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" },
+ { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" },
+ { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" },
+ { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" },
+]
+
+[[package]]
+name = "regex"
+version = "2026.1.15"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/0b/86/07d5056945f9ec4590b518171c4254a5925832eb727b56d3c38a7476f316/regex-2026.1.15.tar.gz", hash = "sha256:164759aa25575cbc0651bef59a0b18353e54300d79ace8084c818ad8ac72b7d5", size = 414811, upload-time = "2026-01-14T23:18:02.775Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d0/c9/0c80c96eab96948363d270143138d671d5731c3a692b417629bf3492a9d6/regex-2026.1.15-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1ae6020fb311f68d753b7efa9d4b9a5d47a5d6466ea0d5e3b5a471a960ea6e4a", size = 488168, upload-time = "2026-01-14T23:14:16.129Z" },
+ { url = "https://files.pythonhosted.org/packages/17/f0/271c92f5389a552494c429e5cc38d76d1322eb142fb5db3c8ccc47751468/regex-2026.1.15-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:eddf73f41225942c1f994914742afa53dc0d01a6e20fe14b878a1b1edc74151f", size = 290636, upload-time = "2026-01-14T23:14:17.715Z" },
+ { url = "https://files.pythonhosted.org/packages/a0/f9/5f1fd077d106ca5655a0f9ff8f25a1ab55b92128b5713a91ed7134ff688e/regex-2026.1.15-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e8cd52557603f5c66a548f69421310886b28b7066853089e1a71ee710e1cdc1", size = 288496, upload-time = "2026-01-14T23:14:19.326Z" },
+ { url = "https://files.pythonhosted.org/packages/b5/e1/8f43b03a4968c748858ec77f746c286d81f896c2e437ccf050ebc5d3128c/regex-2026.1.15-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5170907244b14303edc5978f522f16c974f32d3aa92109fabc2af52411c9433b", size = 793503, upload-time = "2026-01-14T23:14:20.922Z" },
+ { url = "https://files.pythonhosted.org/packages/8d/4e/a39a5e8edc5377a46a7c875c2f9a626ed3338cb3bb06931be461c3e1a34a/regex-2026.1.15-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2748c1ec0663580b4510bd89941a31560b4b439a0b428b49472a3d9944d11cd8", size = 860535, upload-time = "2026-01-14T23:14:22.405Z" },
+ { url = "https://files.pythonhosted.org/packages/dc/1c/9dce667a32a9477f7a2869c1c767dc00727284a9fa3ff5c09a5c6c03575e/regex-2026.1.15-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2f2775843ca49360508d080eaa87f94fa248e2c946bbcd963bb3aae14f333413", size = 907225, upload-time = "2026-01-14T23:14:23.897Z" },
+ { url = "https://files.pythonhosted.org/packages/a4/3c/87ca0a02736d16b6262921425e84b48984e77d8e4e572c9072ce96e66c30/regex-2026.1.15-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9ea2604370efc9a174c1b5dcc81784fb040044232150f7f33756049edfc9026", size = 800526, upload-time = "2026-01-14T23:14:26.039Z" },
+ { url = "https://files.pythonhosted.org/packages/4b/ff/647d5715aeea7c87bdcbd2f578f47b415f55c24e361e639fe8c0cc88878f/regex-2026.1.15-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0dcd31594264029b57bf16f37fd7248a70b3b764ed9e0839a8f271b2d22c0785", size = 773446, upload-time = "2026-01-14T23:14:28.109Z" },
+ { url = "https://files.pythonhosted.org/packages/af/89/bf22cac25cb4ba0fe6bff52ebedbb65b77a179052a9d6037136ae93f42f4/regex-2026.1.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c08c1f3e34338256732bd6938747daa3c0d5b251e04b6e43b5813e94d503076e", size = 783051, upload-time = "2026-01-14T23:14:29.929Z" },
+ { url = "https://files.pythonhosted.org/packages/1e/f4/6ed03e71dca6348a5188363a34f5e26ffd5db1404780288ff0d79513bce4/regex-2026.1.15-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e43a55f378df1e7a4fa3547c88d9a5a9b7113f653a66821bcea4718fe6c58763", size = 854485, upload-time = "2026-01-14T23:14:31.366Z" },
+ { url = "https://files.pythonhosted.org/packages/d9/9a/8e8560bd78caded8eb137e3e47612430a05b9a772caf60876435192d670a/regex-2026.1.15-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:f82110ab962a541737bd0ce87978d4c658f06e7591ba899192e2712a517badbb", size = 762195, upload-time = "2026-01-14T23:14:32.802Z" },
+ { url = "https://files.pythonhosted.org/packages/38/6b/61fc710f9aa8dfcd764fe27d37edfaa023b1a23305a0d84fccd5adb346ea/regex-2026.1.15-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:27618391db7bdaf87ac6c92b31e8f0dfb83a9de0075855152b720140bda177a2", size = 845986, upload-time = "2026-01-14T23:14:34.898Z" },
+ { url = "https://files.pythonhosted.org/packages/fd/2e/fbee4cb93f9d686901a7ca8d94285b80405e8c34fe4107f63ffcbfb56379/regex-2026.1.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bfb0d6be01fbae8d6655c8ca21b3b72458606c4aec9bbc932db758d47aba6db1", size = 788992, upload-time = "2026-01-14T23:14:37.116Z" },
+ { url = "https://files.pythonhosted.org/packages/ed/14/3076348f3f586de64b1ab75a3fbabdaab7684af7f308ad43be7ef1849e55/regex-2026.1.15-cp311-cp311-win32.whl", hash = "sha256:b10e42a6de0e32559a92f2f8dc908478cc0fa02838d7dbe764c44dca3fa13569", size = 265893, upload-time = "2026-01-14T23:14:38.426Z" },
+ { url = "https://files.pythonhosted.org/packages/0f/19/772cf8b5fc803f5c89ba85d8b1870a1ca580dc482aa030383a9289c82e44/regex-2026.1.15-cp311-cp311-win_amd64.whl", hash = "sha256:e9bf3f0bbdb56633c07d7116ae60a576f846efdd86a8848f8d62b749e1209ca7", size = 277840, upload-time = "2026-01-14T23:14:39.785Z" },
+ { url = "https://files.pythonhosted.org/packages/78/84/d05f61142709474da3c0853222d91086d3e1372bcdab516c6fd8d80f3297/regex-2026.1.15-cp311-cp311-win_arm64.whl", hash = "sha256:41aef6f953283291c4e4e6850607bd71502be67779586a61472beacb315c97ec", size = 270374, upload-time = "2026-01-14T23:14:41.592Z" },
+ { url = "https://files.pythonhosted.org/packages/92/81/10d8cf43c807d0326efe874c1b79f22bfb0fb226027b0b19ebc26d301408/regex-2026.1.15-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:4c8fcc5793dde01641a35905d6731ee1548f02b956815f8f1cab89e515a5bdf1", size = 489398, upload-time = "2026-01-14T23:14:43.741Z" },
+ { url = "https://files.pythonhosted.org/packages/90/b0/7c2a74e74ef2a7c32de724658a69a862880e3e4155cba992ba04d1c70400/regex-2026.1.15-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bfd876041a956e6a90ad7cdb3f6a630c07d491280bfeed4544053cd434901681", size = 291339, upload-time = "2026-01-14T23:14:45.183Z" },
+ { url = "https://files.pythonhosted.org/packages/19/4d/16d0773d0c818417f4cc20aa0da90064b966d22cd62a8c46765b5bd2d643/regex-2026.1.15-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9250d087bc92b7d4899ccd5539a1b2334e44eee85d848c4c1aef8e221d3f8c8f", size = 289003, upload-time = "2026-01-14T23:14:47.25Z" },
+ { url = "https://files.pythonhosted.org/packages/c6/e4/1fc4599450c9f0863d9406e944592d968b8d6dfd0d552a7d569e43bceada/regex-2026.1.15-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c8a154cf6537ebbc110e24dabe53095e714245c272da9c1be05734bdad4a61aa", size = 798656, upload-time = "2026-01-14T23:14:48.77Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/e6/59650d73a73fa8a60b3a590545bfcf1172b4384a7df2e7fe7b9aab4e2da9/regex-2026.1.15-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8050ba2e3ea1d8731a549e83c18d2f0999fbc99a5f6bd06b4c91449f55291804", size = 864252, upload-time = "2026-01-14T23:14:50.528Z" },
+ { url = "https://files.pythonhosted.org/packages/6e/ab/1d0f4d50a1638849a97d731364c9a80fa304fec46325e48330c170ee8e80/regex-2026.1.15-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0bf065240704cb8951cc04972cf107063917022511273e0969bdb34fc173456c", size = 912268, upload-time = "2026-01-14T23:14:52.952Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/df/0d722c030c82faa1d331d1921ee268a4e8fb55ca8b9042c9341c352f17fa/regex-2026.1.15-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c32bef3e7aeee75746748643667668ef941d28b003bfc89994ecf09a10f7a1b5", size = 803589, upload-time = "2026-01-14T23:14:55.182Z" },
+ { url = "https://files.pythonhosted.org/packages/66/23/33289beba7ccb8b805c6610a8913d0131f834928afc555b241caabd422a9/regex-2026.1.15-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d5eaa4a4c5b1906bd0d2508d68927f15b81821f85092e06f1a34a4254b0e1af3", size = 775700, upload-time = "2026-01-14T23:14:56.707Z" },
+ { url = "https://files.pythonhosted.org/packages/e7/65/bf3a42fa6897a0d3afa81acb25c42f4b71c274f698ceabd75523259f6688/regex-2026.1.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:86c1077a3cc60d453d4084d5b9649065f3bf1184e22992bd322e1f081d3117fb", size = 787928, upload-time = "2026-01-14T23:14:58.312Z" },
+ { url = "https://files.pythonhosted.org/packages/f4/f5/13bf65864fc314f68cdd6d8ca94adcab064d4d39dbd0b10fef29a9da48fc/regex-2026.1.15-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:2b091aefc05c78d286657cd4db95f2e6313375ff65dcf085e42e4c04d9c8d410", size = 858607, upload-time = "2026-01-14T23:15:00.657Z" },
+ { url = "https://files.pythonhosted.org/packages/a3/31/040e589834d7a439ee43fb0e1e902bc81bd58a5ba81acffe586bb3321d35/regex-2026.1.15-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:57e7d17f59f9ebfa9667e6e5a1c0127b96b87cb9cede8335482451ed00788ba4", size = 763729, upload-time = "2026-01-14T23:15:02.248Z" },
+ { url = "https://files.pythonhosted.org/packages/9b/84/6921e8129687a427edf25a34a5594b588b6d88f491320b9de5b6339a4fcb/regex-2026.1.15-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:c6c4dcdfff2c08509faa15d36ba7e5ef5fcfab25f1e8f85a0c8f45bc3a30725d", size = 850697, upload-time = "2026-01-14T23:15:03.878Z" },
+ { url = "https://files.pythonhosted.org/packages/8a/87/3d06143d4b128f4229158f2de5de6c8f2485170c7221e61bf381313314b2/regex-2026.1.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:cf8ff04c642716a7f2048713ddc6278c5fd41faa3b9cab12607c7abecd012c22", size = 789849, upload-time = "2026-01-14T23:15:06.102Z" },
+ { url = "https://files.pythonhosted.org/packages/77/69/c50a63842b6bd48850ebc7ab22d46e7a2a32d824ad6c605b218441814639/regex-2026.1.15-cp312-cp312-win32.whl", hash = "sha256:82345326b1d8d56afbe41d881fdf62f1926d7264b2fc1537f99ae5da9aad7913", size = 266279, upload-time = "2026-01-14T23:15:07.678Z" },
+ { url = "https://files.pythonhosted.org/packages/f2/36/39d0b29d087e2b11fd8191e15e81cce1b635fcc845297c67f11d0d19274d/regex-2026.1.15-cp312-cp312-win_amd64.whl", hash = "sha256:4def140aa6156bc64ee9912383d4038f3fdd18fee03a6f222abd4de6357ce42a", size = 277166, upload-time = "2026-01-14T23:15:09.257Z" },
+ { url = "https://files.pythonhosted.org/packages/28/32/5b8e476a12262748851fa8ab1b0be540360692325975b094e594dfebbb52/regex-2026.1.15-cp312-cp312-win_arm64.whl", hash = "sha256:c6c565d9a6e1a8d783c1948937ffc377dd5771e83bd56de8317c450a954d2056", size = 270415, upload-time = "2026-01-14T23:15:10.743Z" },
+ { url = "https://files.pythonhosted.org/packages/f8/2e/6870bb16e982669b674cce3ee9ff2d1d46ab80528ee6bcc20fb2292efb60/regex-2026.1.15-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e69d0deeb977ffe7ed3d2e4439360089f9c3f217ada608f0f88ebd67afb6385e", size = 489164, upload-time = "2026-01-14T23:15:13.962Z" },
+ { url = "https://files.pythonhosted.org/packages/dc/67/9774542e203849b0286badf67199970a44ebdb0cc5fb739f06e47ada72f8/regex-2026.1.15-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3601ffb5375de85a16f407854d11cca8fe3f5febbe3ac78fb2866bb220c74d10", size = 291218, upload-time = "2026-01-14T23:15:15.647Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/87/b0cda79f22b8dee05f774922a214da109f9a4c0eca5da2c9d72d77ea062c/regex-2026.1.15-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4c5ef43b5c2d4114eb8ea424bb8c9cec01d5d17f242af88b2448f5ee81caadbc", size = 288895, upload-time = "2026-01-14T23:15:17.788Z" },
+ { url = "https://files.pythonhosted.org/packages/3b/6a/0041f0a2170d32be01ab981d6346c83a8934277d82c780d60b127331f264/regex-2026.1.15-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:968c14d4f03e10b2fd960f1d5168c1f0ac969381d3c1fcc973bc45fb06346599", size = 798680, upload-time = "2026-01-14T23:15:19.342Z" },
+ { url = "https://files.pythonhosted.org/packages/58/de/30e1cfcdbe3e891324aa7568b7c968771f82190df5524fabc1138cb2d45a/regex-2026.1.15-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56a5595d0f892f214609c9f76b41b7428bed439d98dc961efafdd1354d42baae", size = 864210, upload-time = "2026-01-14T23:15:22.005Z" },
+ { url = "https://files.pythonhosted.org/packages/64/44/4db2f5c5ca0ccd40ff052ae7b1e9731352fcdad946c2b812285a7505ca75/regex-2026.1.15-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0bf650f26087363434c4e560011f8e4e738f6f3e029b85d4904c50135b86cfa5", size = 912358, upload-time = "2026-01-14T23:15:24.569Z" },
+ { url = "https://files.pythonhosted.org/packages/79/b6/e6a5665d43a7c42467138c8a2549be432bad22cbd206f5ec87162de74bd7/regex-2026.1.15-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18388a62989c72ac24de75f1449d0fb0b04dfccd0a1a7c1c43af5eb503d890f6", size = 803583, upload-time = "2026-01-14T23:15:26.526Z" },
+ { url = "https://files.pythonhosted.org/packages/e7/53/7cd478222169d85d74d7437e74750005e993f52f335f7c04ff7adfda3310/regex-2026.1.15-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6d220a2517f5893f55daac983bfa9fe998a7dbcaee4f5d27a88500f8b7873788", size = 775782, upload-time = "2026-01-14T23:15:29.352Z" },
+ { url = "https://files.pythonhosted.org/packages/ca/b5/75f9a9ee4b03a7c009fe60500fe550b45df94f0955ca29af16333ef557c5/regex-2026.1.15-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c9c08c2fbc6120e70abff5d7f28ffb4d969e14294fb2143b4b5c7d20e46d1714", size = 787978, upload-time = "2026-01-14T23:15:31.295Z" },
+ { url = "https://files.pythonhosted.org/packages/72/b3/79821c826245bbe9ccbb54f6eadb7879c722fd3e0248c17bfc90bf54e123/regex-2026.1.15-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:7ef7d5d4bd49ec7364315167a4134a015f61e8266c6d446fc116a9ac4456e10d", size = 858550, upload-time = "2026-01-14T23:15:33.558Z" },
+ { url = "https://files.pythonhosted.org/packages/4a/85/2ab5f77a1c465745bfbfcb3ad63178a58337ae8d5274315e2cc623a822fa/regex-2026.1.15-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:6e42844ad64194fa08d5ccb75fe6a459b9b08e6d7296bd704460168d58a388f3", size = 763747, upload-time = "2026-01-14T23:15:35.206Z" },
+ { url = "https://files.pythonhosted.org/packages/6d/84/c27df502d4bfe2873a3e3a7cf1bdb2b9cc10284d1a44797cf38bed790470/regex-2026.1.15-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:cfecdaa4b19f9ca534746eb3b55a5195d5c95b88cac32a205e981ec0a22b7d31", size = 850615, upload-time = "2026-01-14T23:15:37.523Z" },
+ { url = "https://files.pythonhosted.org/packages/7d/b7/658a9782fb253680aa8ecb5ccbb51f69e088ed48142c46d9f0c99b46c575/regex-2026.1.15-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:08df9722d9b87834a3d701f3fca570b2be115654dbfd30179f30ab2f39d606d3", size = 789951, upload-time = "2026-01-14T23:15:39.582Z" },
+ { url = "https://files.pythonhosted.org/packages/fc/2a/5928af114441e059f15b2f63e188bd00c6529b3051c974ade7444b85fcda/regex-2026.1.15-cp313-cp313-win32.whl", hash = "sha256:d426616dae0967ca225ab12c22274eb816558f2f99ccb4a1d52ca92e8baf180f", size = 266275, upload-time = "2026-01-14T23:15:42.108Z" },
+ { url = "https://files.pythonhosted.org/packages/4f/16/5bfbb89e435897bff28cf0352a992ca719d9e55ebf8b629203c96b6ce4f7/regex-2026.1.15-cp313-cp313-win_amd64.whl", hash = "sha256:febd38857b09867d3ed3f4f1af7d241c5c50362e25ef43034995b77a50df494e", size = 277145, upload-time = "2026-01-14T23:15:44.244Z" },
+ { url = "https://files.pythonhosted.org/packages/56/c1/a09ff7392ef4233296e821aec5f78c51be5e91ffde0d163059e50fd75835/regex-2026.1.15-cp313-cp313-win_arm64.whl", hash = "sha256:8e32f7896f83774f91499d239e24cebfadbc07639c1494bb7213983842348337", size = 270411, upload-time = "2026-01-14T23:15:45.858Z" },
+ { url = "https://files.pythonhosted.org/packages/3c/38/0cfd5a78e5c6db00e6782fdae70458f89850ce95baa5e8694ab91d89744f/regex-2026.1.15-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:ec94c04149b6a7b8120f9f44565722c7ae31b7a6d2275569d2eefa76b83da3be", size = 492068, upload-time = "2026-01-14T23:15:47.616Z" },
+ { url = "https://files.pythonhosted.org/packages/50/72/6c86acff16cb7c959c4355826bbf06aad670682d07c8f3998d9ef4fee7cd/regex-2026.1.15-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:40c86d8046915bb9aeb15d3f3f15b6fd500b8ea4485b30e1bbc799dab3fe29f8", size = 292756, upload-time = "2026-01-14T23:15:49.307Z" },
+ { url = "https://files.pythonhosted.org/packages/4e/58/df7fb69eadfe76526ddfce28abdc0af09ffe65f20c2c90932e89d705153f/regex-2026.1.15-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:726ea4e727aba21643205edad8f2187ec682d3305d790f73b7a51c7587b64bdd", size = 291114, upload-time = "2026-01-14T23:15:51.484Z" },
+ { url = "https://files.pythonhosted.org/packages/ed/6c/a4011cd1cf96b90d2cdc7e156f91efbd26531e822a7fbb82a43c1016678e/regex-2026.1.15-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1cb740d044aff31898804e7bf1181cc72c03d11dfd19932b9911ffc19a79070a", size = 807524, upload-time = "2026-01-14T23:15:53.102Z" },
+ { url = "https://files.pythonhosted.org/packages/1d/25/a53ffb73183f69c3e9f4355c4922b76d2840aee160af6af5fac229b6201d/regex-2026.1.15-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:05d75a668e9ea16f832390d22131fe1e8acc8389a694c8febc3e340b0f810b93", size = 873455, upload-time = "2026-01-14T23:15:54.956Z" },
+ { url = "https://files.pythonhosted.org/packages/66/0b/8b47fc2e8f97d9b4a851736f3890a5f786443aa8901061c55f24c955f45b/regex-2026.1.15-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d991483606f3dbec93287b9f35596f41aa2e92b7c2ebbb935b63f409e243c9af", size = 915007, upload-time = "2026-01-14T23:15:57.041Z" },
+ { url = "https://files.pythonhosted.org/packages/c2/fa/97de0d681e6d26fabe71968dbee06dd52819e9a22fdce5dac7256c31ed84/regex-2026.1.15-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:194312a14819d3e44628a44ed6fea6898fdbecb0550089d84c403475138d0a09", size = 812794, upload-time = "2026-01-14T23:15:58.916Z" },
+ { url = "https://files.pythonhosted.org/packages/22/38/e752f94e860d429654aa2b1c51880bff8dfe8f084268258adf9151cf1f53/regex-2026.1.15-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fe2fda4110a3d0bc163c2e0664be44657431440722c5c5315c65155cab92f9e5", size = 781159, upload-time = "2026-01-14T23:16:00.817Z" },
+ { url = "https://files.pythonhosted.org/packages/e9/a7/d739ffaef33c378fc888302a018d7f81080393d96c476b058b8c64fd2b0d/regex-2026.1.15-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:124dc36c85d34ef2d9164da41a53c1c8c122cfb1f6e1ec377a1f27ee81deb794", size = 795558, upload-time = "2026-01-14T23:16:03.267Z" },
+ { url = "https://files.pythonhosted.org/packages/3e/c4/542876f9a0ac576100fc73e9c75b779f5c31e3527576cfc9cb3009dcc58a/regex-2026.1.15-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:a1774cd1981cd212506a23a14dba7fdeaee259f5deba2df6229966d9911e767a", size = 868427, upload-time = "2026-01-14T23:16:05.646Z" },
+ { url = "https://files.pythonhosted.org/packages/fc/0f/d5655bea5b22069e32ae85a947aa564912f23758e112cdb74212848a1a1b/regex-2026.1.15-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:b5f7d8d2867152cdb625e72a530d2ccb48a3d199159144cbdd63870882fb6f80", size = 769939, upload-time = "2026-01-14T23:16:07.542Z" },
+ { url = "https://files.pythonhosted.org/packages/20/06/7e18a4fa9d326daeda46d471a44ef94201c46eaa26dbbb780b5d92cbfdda/regex-2026.1.15-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:492534a0ab925d1db998defc3c302dae3616a2fc3fe2e08db1472348f096ddf2", size = 854753, upload-time = "2026-01-14T23:16:10.395Z" },
+ { url = "https://files.pythonhosted.org/packages/3b/67/dc8946ef3965e166f558ef3b47f492bc364e96a265eb4a2bb3ca765c8e46/regex-2026.1.15-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c661fc820cfb33e166bf2450d3dadbda47c8d8981898adb9b6fe24e5e582ba60", size = 799559, upload-time = "2026-01-14T23:16:12.347Z" },
+ { url = "https://files.pythonhosted.org/packages/a5/61/1bba81ff6d50c86c65d9fd84ce9699dd106438ee4cdb105bf60374ee8412/regex-2026.1.15-cp313-cp313t-win32.whl", hash = "sha256:99ad739c3686085e614bf77a508e26954ff1b8f14da0e3765ff7abbf7799f952", size = 268879, upload-time = "2026-01-14T23:16:14.049Z" },
+ { url = "https://files.pythonhosted.org/packages/e9/5e/cef7d4c5fb0ea3ac5c775fd37db5747f7378b29526cc83f572198924ff47/regex-2026.1.15-cp313-cp313t-win_amd64.whl", hash = "sha256:32655d17905e7ff8ba5c764c43cb124e34a9245e45b83c22e81041e1071aee10", size = 280317, upload-time = "2026-01-14T23:16:15.718Z" },
+ { url = "https://files.pythonhosted.org/packages/b4/52/4317f7a5988544e34ab57b4bde0f04944c4786128c933fb09825924d3e82/regex-2026.1.15-cp313-cp313t-win_arm64.whl", hash = "sha256:b2a13dd6a95e95a489ca242319d18fc02e07ceb28fa9ad146385194d95b3c829", size = 271551, upload-time = "2026-01-14T23:16:17.533Z" },
+ { url = "https://files.pythonhosted.org/packages/52/0a/47fa888ec7cbbc7d62c5f2a6a888878e76169170ead271a35239edd8f0e8/regex-2026.1.15-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:d920392a6b1f353f4aa54328c867fec3320fa50657e25f64abf17af054fc97ac", size = 489170, upload-time = "2026-01-14T23:16:19.835Z" },
+ { url = "https://files.pythonhosted.org/packages/ac/c4/d000e9b7296c15737c9301708e9e7fbdea009f8e93541b6b43bdb8219646/regex-2026.1.15-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b5a28980a926fa810dbbed059547b02783952e2efd9c636412345232ddb87ff6", size = 291146, upload-time = "2026-01-14T23:16:21.541Z" },
+ { url = "https://files.pythonhosted.org/packages/f9/b6/921cc61982e538682bdf3bdf5b2c6ab6b34368da1f8e98a6c1ddc503c9cf/regex-2026.1.15-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:621f73a07595d83f28952d7bd1e91e9d1ed7625fb7af0064d3516674ec93a2a2", size = 288986, upload-time = "2026-01-14T23:16:23.381Z" },
+ { url = "https://files.pythonhosted.org/packages/ca/33/eb7383dde0bbc93f4fb9d03453aab97e18ad4024ac7e26cef8d1f0a2cff0/regex-2026.1.15-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3d7d92495f47567a9b1669c51fc8d6d809821849063d168121ef801bbc213846", size = 799098, upload-time = "2026-01-14T23:16:25.088Z" },
+ { url = "https://files.pythonhosted.org/packages/27/56/b664dccae898fc8d8b4c23accd853f723bde0f026c747b6f6262b688029c/regex-2026.1.15-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8dd16fba2758db7a3780a051f245539c4451ca20910f5a5e6ea1c08d06d4a76b", size = 864980, upload-time = "2026-01-14T23:16:27.297Z" },
+ { url = "https://files.pythonhosted.org/packages/16/40/0999e064a170eddd237bae9ccfcd8f28b3aa98a38bf727a086425542a4fc/regex-2026.1.15-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1e1808471fbe44c1a63e5f577a1d5f02fe5d66031dcbdf12f093ffc1305a858e", size = 911607, upload-time = "2026-01-14T23:16:29.235Z" },
+ { url = "https://files.pythonhosted.org/packages/07/78/c77f644b68ab054e5a674fb4da40ff7bffb2c88df58afa82dbf86573092d/regex-2026.1.15-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0751a26ad39d4f2ade8fe16c59b2bf5cb19eb3d2cd543e709e583d559bd9efde", size = 803358, upload-time = "2026-01-14T23:16:31.369Z" },
+ { url = "https://files.pythonhosted.org/packages/27/31/d4292ea8566eaa551fafc07797961c5963cf5235c797cc2ae19b85dfd04d/regex-2026.1.15-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0f0c7684c7f9ca241344ff95a1de964f257a5251968484270e91c25a755532c5", size = 775833, upload-time = "2026-01-14T23:16:33.141Z" },
+ { url = "https://files.pythonhosted.org/packages/ce/b2/cff3bf2fea4133aa6fb0d1e370b37544d18c8350a2fa118c7e11d1db0e14/regex-2026.1.15-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:74f45d170a21df41508cb67165456538425185baaf686281fa210d7e729abc34", size = 788045, upload-time = "2026-01-14T23:16:35.005Z" },
+ { url = "https://files.pythonhosted.org/packages/8d/99/2cb9b69045372ec877b6f5124bda4eb4253bc58b8fe5848c973f752bc52c/regex-2026.1.15-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:f1862739a1ffb50615c0fde6bae6569b5efbe08d98e59ce009f68a336f64da75", size = 859374, upload-time = "2026-01-14T23:16:36.919Z" },
+ { url = "https://files.pythonhosted.org/packages/09/16/710b0a5abe8e077b1729a562d2f297224ad079f3a66dce46844c193416c8/regex-2026.1.15-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:453078802f1b9e2b7303fb79222c054cb18e76f7bdc220f7530fdc85d319f99e", size = 763940, upload-time = "2026-01-14T23:16:38.685Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/d1/7585c8e744e40eb3d32f119191969b91de04c073fca98ec14299041f6e7e/regex-2026.1.15-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:a30a68e89e5a218b8b23a52292924c1f4b245cb0c68d1cce9aec9bbda6e2c160", size = 850112, upload-time = "2026-01-14T23:16:40.646Z" },
+ { url = "https://files.pythonhosted.org/packages/af/d6/43e1dd85df86c49a347aa57c1f69d12c652c7b60e37ec162e3096194a278/regex-2026.1.15-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9479cae874c81bf610d72b85bb681a94c95722c127b55445285fb0e2c82db8e1", size = 789586, upload-time = "2026-01-14T23:16:42.799Z" },
+ { url = "https://files.pythonhosted.org/packages/93/38/77142422f631e013f316aaae83234c629555729a9fbc952b8a63ac91462a/regex-2026.1.15-cp314-cp314-win32.whl", hash = "sha256:d639a750223132afbfb8f429c60d9d318aeba03281a5f1ab49f877456448dcf1", size = 271691, upload-time = "2026-01-14T23:16:44.671Z" },
+ { url = "https://files.pythonhosted.org/packages/4a/a9/ab16b4649524ca9e05213c1cdbb7faa85cc2aa90a0230d2f796cbaf22736/regex-2026.1.15-cp314-cp314-win_amd64.whl", hash = "sha256:4161d87f85fa831e31469bfd82c186923070fc970b9de75339b68f0c75b51903", size = 280422, upload-time = "2026-01-14T23:16:46.607Z" },
+ { url = "https://files.pythonhosted.org/packages/be/2a/20fd057bf3521cb4791f69f869635f73e0aaf2b9ad2d260f728144f9047c/regex-2026.1.15-cp314-cp314-win_arm64.whl", hash = "sha256:91c5036ebb62663a6b3999bdd2e559fd8456d17e2b485bf509784cd31a8b1705", size = 273467, upload-time = "2026-01-14T23:16:48.967Z" },
+ { url = "https://files.pythonhosted.org/packages/ad/77/0b1e81857060b92b9cad239104c46507dd481b3ff1fa79f8e7f865aae38a/regex-2026.1.15-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:ee6854c9000a10938c79238de2379bea30c82e4925a371711af45387df35cab8", size = 492073, upload-time = "2026-01-14T23:16:51.154Z" },
+ { url = "https://files.pythonhosted.org/packages/70/f3/f8302b0c208b22c1e4f423147e1913fd475ddd6230565b299925353de644/regex-2026.1.15-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2c2b80399a422348ce5de4fe40c418d6299a0fa2803dd61dc0b1a2f28e280fcf", size = 292757, upload-time = "2026-01-14T23:16:53.08Z" },
+ { url = "https://files.pythonhosted.org/packages/bf/f0/ef55de2460f3b4a6da9d9e7daacd0cb79d4ef75c64a2af316e68447f0df0/regex-2026.1.15-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:dca3582bca82596609959ac39e12b7dad98385b4fefccb1151b937383cec547d", size = 291122, upload-time = "2026-01-14T23:16:55.383Z" },
+ { url = "https://files.pythonhosted.org/packages/cf/55/bb8ccbacabbc3a11d863ee62a9f18b160a83084ea95cdfc5d207bfc3dd75/regex-2026.1.15-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef71d476caa6692eea743ae5ea23cde3260677f70122c4d258ca952e5c2d4e84", size = 807761, upload-time = "2026-01-14T23:16:57.251Z" },
+ { url = "https://files.pythonhosted.org/packages/8f/84/f75d937f17f81e55679a0509e86176e29caa7298c38bd1db7ce9c0bf6075/regex-2026.1.15-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c243da3436354f4af6c3058a3f81a97d47ea52c9bd874b52fd30274853a1d5df", size = 873538, upload-time = "2026-01-14T23:16:59.349Z" },
+ { url = "https://files.pythonhosted.org/packages/b8/d9/0da86327df70349aa8d86390da91171bd3ca4f0e7c1d1d453a9c10344da3/regex-2026.1.15-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8355ad842a7c7e9e5e55653eade3b7d1885ba86f124dd8ab1f722f9be6627434", size = 915066, upload-time = "2026-01-14T23:17:01.607Z" },
+ { url = "https://files.pythonhosted.org/packages/2a/5e/f660fb23fc77baa2a61aa1f1fe3a4eea2bbb8a286ddec148030672e18834/regex-2026.1.15-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f192a831d9575271a22d804ff1a5355355723f94f31d9eef25f0d45a152fdc1a", size = 812938, upload-time = "2026-01-14T23:17:04.366Z" },
+ { url = "https://files.pythonhosted.org/packages/69/33/a47a29bfecebbbfd1e5cd3f26b28020a97e4820f1c5148e66e3b7d4b4992/regex-2026.1.15-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:166551807ec20d47ceaeec380081f843e88c8949780cd42c40f18d16168bed10", size = 781314, upload-time = "2026-01-14T23:17:06.378Z" },
+ { url = "https://files.pythonhosted.org/packages/65/ec/7ec2bbfd4c3f4e494a24dec4c6943a668e2030426b1b8b949a6462d2c17b/regex-2026.1.15-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:f9ca1cbdc0fbfe5e6e6f8221ef2309988db5bcede52443aeaee9a4ad555e0dac", size = 795652, upload-time = "2026-01-14T23:17:08.521Z" },
+ { url = "https://files.pythonhosted.org/packages/46/79/a5d8651ae131fe27d7c521ad300aa7f1c7be1dbeee4d446498af5411b8a9/regex-2026.1.15-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b30bcbd1e1221783c721483953d9e4f3ab9c5d165aa709693d3f3946747b1aea", size = 868550, upload-time = "2026-01-14T23:17:10.573Z" },
+ { url = "https://files.pythonhosted.org/packages/06/b7/25635d2809664b79f183070786a5552dd4e627e5aedb0065f4e3cf8ee37d/regex-2026.1.15-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:2a8d7b50c34578d0d3bf7ad58cde9652b7d683691876f83aedc002862a35dc5e", size = 769981, upload-time = "2026-01-14T23:17:12.871Z" },
+ { url = "https://files.pythonhosted.org/packages/16/8b/fc3fcbb2393dcfa4a6c5ffad92dc498e842df4581ea9d14309fcd3c55fb9/regex-2026.1.15-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:9d787e3310c6a6425eb346be4ff2ccf6eece63017916fd77fe8328c57be83521", size = 854780, upload-time = "2026-01-14T23:17:14.837Z" },
+ { url = "https://files.pythonhosted.org/packages/d0/38/dde117c76c624713c8a2842530be9c93ca8b606c0f6102d86e8cd1ce8bea/regex-2026.1.15-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:619843841e220adca114118533a574a9cd183ed8a28b85627d2844c500a2b0db", size = 799778, upload-time = "2026-01-14T23:17:17.369Z" },
+ { url = "https://files.pythonhosted.org/packages/e3/0d/3a6cfa9ae99606afb612d8fb7a66b245a9d5ff0f29bb347c8a30b6ad561b/regex-2026.1.15-cp314-cp314t-win32.whl", hash = "sha256:e90b8db97f6f2c97eb045b51a6b2c5ed69cedd8392459e0642d4199b94fabd7e", size = 274667, upload-time = "2026-01-14T23:17:19.301Z" },
+ { url = "https://files.pythonhosted.org/packages/5b/b2/297293bb0742fd06b8d8e2572db41a855cdf1cae0bf009b1cb74fe07e196/regex-2026.1.15-cp314-cp314t-win_amd64.whl", hash = "sha256:5ef19071f4ac9f0834793af85bd04a920b4407715624e40cb7a0631a11137cdf", size = 284386, upload-time = "2026-01-14T23:17:21.231Z" },
+ { url = "https://files.pythonhosted.org/packages/95/e4/a3b9480c78cf8ee86626cb06f8d931d74d775897d44201ccb813097ae697/regex-2026.1.15-cp314-cp314t-win_arm64.whl", hash = "sha256:ca89c5e596fc05b015f27561b3793dc2fa0917ea0d7507eebb448efd35274a70", size = 274837, upload-time = "2026-01-14T23:17:23.146Z" },
+]
+
+[[package]]
+name = "requests"
+version = "2.32.5"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "certifi" },
+ { name = "charset-normalizer" },
+ { name = "idna" },
+ { name = "urllib3" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" },
+]
+
+[[package]]
+name = "requests-toolbelt"
+version = "1.0.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "requests" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/f3/61/d7545dafb7ac2230c70d38d31cbfe4cc64f7144dc41f6e4e4b78ecd9f5bb/requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6", size = 206888, upload-time = "2023-05-01T04:11:33.229Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06", size = 54481, upload-time = "2023-05-01T04:11:28.427Z" },
+]
+
+[[package]]
+name = "sniffio"
+version = "1.3.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" },
+]
+
+[[package]]
+name = "tavily-python"
+version = "0.7.21"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "httpx" },
+ { name = "requests" },
+ { name = "tiktoken" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/ff/1f/9d5c4ca7034754d1fc232af64638b905162bdf3012e9629030e3d755856f/tavily_python-0.7.21.tar.gz", hash = "sha256:897bedf9b1c2fad8605be642e417d6c7ec1b79bf6199563477cf69c4313f824a", size = 21813, upload-time = "2026-01-30T16:57:33.186Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3a/39/85e5be4e9a912022f86f38288d1f4dd2d100b60ec75ebf3da37ca0122375/tavily_python-0.7.21-py3-none-any.whl", hash = "sha256:acfb5b62f2d1053d56321b4fb1ddfd2e98bb975cc4446b86b3fe2d3dd0850288", size = 17957, upload-time = "2026-01-30T16:57:32.278Z" },
+]
+
+[[package]]
+name = "tenacity"
+version = "9.1.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/0a/d4/2b0cd0fe285e14b36db076e78c93766ff1d529d70408bd1d2a5a84f1d929/tenacity-9.1.2.tar.gz", hash = "sha256:1169d376c297e7de388d18b4481760d478b0e99a777cad3a9c86e556f4b697cb", size = 48036, upload-time = "2025-04-02T08:25:09.966Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e5/30/643397144bfbfec6f6ef821f36f33e57d35946c44a2352d3c9f0ae847619/tenacity-9.1.2-py3-none-any.whl", hash = "sha256:f77bf36710d8b73a50b2dd155c97b870017ad21afe6ab300326b0371b3b05138", size = 28248, upload-time = "2025-04-02T08:25:07.678Z" },
+]
+
+[[package]]
+name = "tiktoken"
+version = "0.12.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "regex" },
+ { name = "requests" },
+]
+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/de/46/21ea696b21f1d6d1efec8639c204bdf20fde8bafb351e1355c72c5d7de52/tiktoken-0.12.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6e227c7f96925003487c33b1b32265fad2fbcec2b7cf4817afb76d416f40f6bb", size = 1051565, upload-time = "2025-10-06T20:21:44.566Z" },
+ { url = "https://files.pythonhosted.org/packages/c9/d9/35c5d2d9e22bb2a5f74ba48266fb56c63d76ae6f66e02feb628671c0283e/tiktoken-0.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c06cf0fcc24c2cb2adb5e185c7082a82cba29c17575e828518c2f11a01f445aa", size = 995284, upload-time = "2025-10-06T20:21:45.622Z" },
+ { url = "https://files.pythonhosted.org/packages/01/84/961106c37b8e49b9fdcf33fe007bb3a8fdcc380c528b20cc7fbba80578b8/tiktoken-0.12.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:f18f249b041851954217e9fd8e5c00b024ab2315ffda5ed77665a05fa91f42dc", size = 1129201, upload-time = "2025-10-06T20:21:47.074Z" },
+ { url = "https://files.pythonhosted.org/packages/6a/d0/3d9275198e067f8b65076a68894bb52fd253875f3644f0a321a720277b8a/tiktoken-0.12.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:47a5bc270b8c3db00bb46ece01ef34ad050e364b51d406b6f9730b64ac28eded", size = 1152444, upload-time = "2025-10-06T20:21:48.139Z" },
+ { url = "https://files.pythonhosted.org/packages/78/db/a58e09687c1698a7c592e1038e01c206569b86a0377828d51635561f8ebf/tiktoken-0.12.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:508fa71810c0efdcd1b898fda574889ee62852989f7c1667414736bcb2b9a4bd", size = 1195080, upload-time = "2025-10-06T20:21:49.246Z" },
+ { url = "https://files.pythonhosted.org/packages/9e/1b/a9e4d2bf91d515c0f74afc526fd773a812232dd6cda33ebea7f531202325/tiktoken-0.12.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a1af81a6c44f008cba48494089dd98cccb8b313f55e961a52f5b222d1e507967", size = 1255240, upload-time = "2025-10-06T20:21:50.274Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/15/963819345f1b1fb0809070a79e9dd96938d4ca41297367d471733e79c76c/tiktoken-0.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:3e68e3e593637b53e56f7237be560f7a394451cb8c11079755e80ae64b9e6def", size = 879422, upload-time = "2025-10-06T20:21:51.734Z" },
+ { 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" },
+ { url = "https://files.pythonhosted.org/packages/f5/de/9341a6d7a8f1b448573bbf3425fa57669ac58258a667eb48a25dfe916d70/tiktoken-0.12.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:d186a5c60c6a0213f04a7a802264083dea1bbde92a2d4c7069e1a56630aef830", size = 1151216, upload-time = "2025-10-06T20:22:23.085Z" },
+ { url = "https://files.pythonhosted.org/packages/75/0d/881866647b8d1be4d67cb24e50d0c26f9f807f994aa1510cb9ba2fe5f612/tiktoken-0.12.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:604831189bd05480f2b885ecd2d1986dc7686f609de48208ebbbddeea071fc0b", size = 1194860, upload-time = "2025-10-06T20:22:24.602Z" },
+ { url = "https://files.pythonhosted.org/packages/b3/1e/b651ec3059474dab649b8d5b69f5c65cd8fcd8918568c1935bd4136c9392/tiktoken-0.12.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:8f317e8530bb3a222547b85a58583238c8f74fd7a7408305f9f63246d1a0958b", size = 1254567, upload-time = "2025-10-06T20:22:25.671Z" },
+ { url = "https://files.pythonhosted.org/packages/80/57/ce64fd16ac390fafde001268c364d559447ba09b509181b2808622420eec/tiktoken-0.12.0-cp314-cp314-win_amd64.whl", hash = "sha256:399c3dd672a6406719d84442299a490420b458c44d3ae65516302a99675888f3", size = 921067, upload-time = "2025-10-06T20:22:26.753Z" },
+ { url = "https://files.pythonhosted.org/packages/ac/a4/72eed53e8976a099539cdd5eb36f241987212c29629d0a52c305173e0a68/tiktoken-0.12.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:c2c714c72bc00a38ca969dae79e8266ddec999c7ceccd603cc4f0d04ccd76365", size = 1050473, upload-time = "2025-10-06T20:22:27.775Z" },
+ { url = "https://files.pythonhosted.org/packages/e6/d7/0110b8f54c008466b19672c615f2168896b83706a6611ba6e47313dbc6e9/tiktoken-0.12.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:cbb9a3ba275165a2cb0f9a83f5d7025afe6b9d0ab01a22b50f0e74fee2ad253e", size = 993855, upload-time = "2025-10-06T20:22:28.799Z" },
+ { url = "https://files.pythonhosted.org/packages/5f/77/4f268c41a3957c418b084dd576ea2fad2e95da0d8e1ab705372892c2ca22/tiktoken-0.12.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:dfdfaa5ffff8993a3af94d1125870b1d27aed7cb97aa7eb8c1cefdbc87dbee63", size = 1129022, upload-time = "2025-10-06T20:22:29.981Z" },
+ { url = "https://files.pythonhosted.org/packages/4e/2b/fc46c90fe5028bd094cd6ee25a7db321cb91d45dc87531e2bdbb26b4867a/tiktoken-0.12.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:584c3ad3d0c74f5269906eb8a659c8bfc6144a52895d9261cdaf90a0ae5f4de0", size = 1150736, upload-time = "2025-10-06T20:22:30.996Z" },
+ { url = "https://files.pythonhosted.org/packages/28/c0/3c7a39ff68022ddfd7d93f3337ad90389a342f761c4d71de99a3ccc57857/tiktoken-0.12.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:54c891b416a0e36b8e2045b12b33dd66fb34a4fe7965565f1b482da50da3e86a", size = 1194908, upload-time = "2025-10-06T20:22:32.073Z" },
+ { url = "https://files.pythonhosted.org/packages/ab/0d/c1ad6f4016a3968c048545f5d9b8ffebf577774b2ede3e2e352553b685fe/tiktoken-0.12.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5edb8743b88d5be814b1a8a8854494719080c28faaa1ccbef02e87354fe71ef0", size = 1253706, upload-time = "2025-10-06T20:22:33.385Z" },
+ { url = "https://files.pythonhosted.org/packages/af/df/c7891ef9d2712ad774777271d39fdef63941ffba0a9d59b7ad1fd2765e57/tiktoken-0.12.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f61c0aea5565ac82e2ec50a05e02a6c44734e91b51c10510b084ea1b8e633a71", size = 920667, upload-time = "2025-10-06T20:22:34.444Z" },
+]
+
+[[package]]
+name = "tqdm"
+version = "4.67.3"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/09/a9/6ba95a270c6f1fbcd8dac228323f2777d886cb206987444e4bce66338dd4/tqdm-4.67.3.tar.gz", hash = "sha256:7d825f03f89244ef73f1d4ce193cb1774a8179fd96f31d7e1dcde62092b960bb", size = 169598, upload-time = "2026-02-03T17:35:53.048Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl", hash = "sha256:ee1e4c0e59148062281c49d80b25b67771a127c85fc9676d3be5f243206826bf", size = 78374, upload-time = "2026-02-03T17:35:50.982Z" },
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.15.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
+]
+
+[[package]]
+name = "typing-inspection"
+version = "0.4.2"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" },
+]
+
+[[package]]
+name = "urllib3"
+version = "2.6.3"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/c7/24/5f1b3bdffd70275f6661c76461e25f024d5a38a46f04aaca912426a2b1d3/urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed", size = 435556, upload-time = "2026-01-07T16:24:43.925Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4", size = 131584, upload-time = "2026-01-07T16:24:42.685Z" },
+]
+
+[[package]]
+name = "uuid-utils"
+version = "0.14.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/57/7c/3a926e847516e67bc6838634f2e54e24381105b4e80f9338dc35cca0086b/uuid_utils-0.14.0.tar.gz", hash = "sha256:fc5bac21e9933ea6c590433c11aa54aaca599f690c08069e364eb13a12f670b4", size = 22072, upload-time = "2026-01-20T20:37:15.729Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/a7/42/42d003f4a99ddc901eef2fd41acb3694163835e037fb6dde79ad68a72342/uuid_utils-0.14.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:f6695c0bed8b18a904321e115afe73b34444bc8451d0ce3244a1ec3b84deb0e5", size = 601786, upload-time = "2026-01-20T20:37:09.843Z" },
+ { url = "https://files.pythonhosted.org/packages/96/e6/775dfb91f74b18f7207e3201eb31ee666d286579990dc69dd50db2d92813/uuid_utils-0.14.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:4f0a730bbf2d8bb2c11b93e1005e91769f2f533fa1125ed1f00fd15b6fcc732b", size = 303943, upload-time = "2026-01-20T20:37:18.767Z" },
+ { url = "https://files.pythonhosted.org/packages/17/82/ea5f5e85560b08a1f30cdc65f75e76494dc7aba9773f679e7eaa27370229/uuid_utils-0.14.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40ce3fd1a4fdedae618fc3edc8faf91897012469169d600133470f49fd699ed3", size = 340467, upload-time = "2026-01-20T20:37:11.794Z" },
+ { url = "https://files.pythonhosted.org/packages/ca/33/54b06415767f4569882e99b6470c6c8eeb97422686a6d432464f9967fd91/uuid_utils-0.14.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:09ae4a98416a440e78f7d9543d11b11cae4bab538b7ed94ec5da5221481748f2", size = 346333, upload-time = "2026-01-20T20:37:12.818Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/10/a6bce636b8f95e65dc84bf4a58ce8205b8e0a2a300a38cdbc83a3f763d27/uuid_utils-0.14.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:971e8c26b90d8ae727e7f2ac3ee23e265971d448b3672882f2eb44828b2b8c3e", size = 470859, upload-time = "2026-01-20T20:37:01.512Z" },
+ { url = "https://files.pythonhosted.org/packages/8a/27/84121c51ea72f013f0e03d0886bcdfa96b31c9b83c98300a7bd5cc4fa191/uuid_utils-0.14.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5cde1fa82804a8f9d2907b7aec2009d440062c63f04abbdb825fce717a5e860", size = 341988, upload-time = "2026-01-20T20:37:22.881Z" },
+ { url = "https://files.pythonhosted.org/packages/90/a4/01c1c7af5e6a44f20b40183e8dac37d6ed83e7dc9e8df85370a15959b804/uuid_utils-0.14.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c7343862a2359e0bd48a7f3dfb5105877a1728677818bb694d9f40703264a2db", size = 365784, upload-time = "2026-01-20T20:37:10.808Z" },
+ { url = "https://files.pythonhosted.org/packages/04/f0/65ee43ec617b8b6b1bf2a5aecd56a069a08cca3d9340c1de86024331bde3/uuid_utils-0.14.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c51e4818fdb08ccec12dc7083a01f49507b4608770a0ab22368001685d59381b", size = 523750, upload-time = "2026-01-20T20:37:06.152Z" },
+ { url = "https://files.pythonhosted.org/packages/95/d3/6bf503e3f135a5dfe705a65e6f89f19bccd55ac3fb16cb5d3ec5ba5388b8/uuid_utils-0.14.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:181bbcccb6f93d80a8504b5bd47b311a1c31395139596edbc47b154b0685b533", size = 615818, upload-time = "2026-01-20T20:37:21.816Z" },
+ { url = "https://files.pythonhosted.org/packages/df/6c/99937dd78d07f73bba831c8dc9469dfe4696539eba2fc269ae1b92752f9e/uuid_utils-0.14.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:5c8ae96101c3524ba8dbf762b6f05e9e9d896544786c503a727c5bf5cb9af1a7", size = 580831, upload-time = "2026-01-20T20:37:19.691Z" },
+ { url = "https://files.pythonhosted.org/packages/44/fa/bbc9e2c25abd09a293b9b097a0d8fc16acd6a92854f0ec080f1ea7ad8bb3/uuid_utils-0.14.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:00ac3c6edfdaff7e1eed041f4800ae09a3361287be780d7610a90fdcde9befdc", size = 546333, upload-time = "2026-01-20T20:37:03.117Z" },
+ { url = "https://files.pythonhosted.org/packages/e7/9b/e5e99b324b1b5f0c62882230455786df0bc66f67eff3b452447e703f45d2/uuid_utils-0.14.0-cp39-abi3-win32.whl", hash = "sha256:ec2fd80adf8e0e6589d40699e6f6df94c93edcc16dd999be0438dd007c77b151", size = 177319, upload-time = "2026-01-20T20:37:04.208Z" },
+ { url = "https://files.pythonhosted.org/packages/d3/28/2c7d417ea483b6ff7820c948678fdf2ac98899dc7e43bb15852faa95acaf/uuid_utils-0.14.0-cp39-abi3-win_amd64.whl", hash = "sha256:efe881eb43a5504fad922644cb93d725fd8a6a6d949bd5a4b4b7d1a1587c7fd1", size = 182566, upload-time = "2026-01-20T20:37:16.868Z" },
+ { url = "https://files.pythonhosted.org/packages/b8/86/49e4bdda28e962fbd7266684171ee29b3d92019116971d58783e51770745/uuid_utils-0.14.0-cp39-abi3-win_arm64.whl", hash = "sha256:32b372b8fd4ebd44d3a219e093fe981af4afdeda2994ee7db208ab065cfcd080", size = 182809, upload-time = "2026-01-20T20:37:05.139Z" },
+ { url = "https://files.pythonhosted.org/packages/f1/03/1f1146e32e94d1f260dfabc81e1649102083303fb4ad549775c943425d9a/uuid_utils-0.14.0-pp311-pypy311_pp73-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:762e8d67992ac4d2454e24a141a1c82142b5bde10409818c62adbe9924ebc86d", size = 587430, upload-time = "2026-01-20T20:37:24.998Z" },
+ { url = "https://files.pythonhosted.org/packages/87/ba/d5a7469362594d885fd9219fe9e851efbe65101d3ef1ef25ea321d7ce841/uuid_utils-0.14.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:40be5bf0b13aa849d9062abc86c198be6a25ff35316ce0b89fc25f3bac6d525e", size = 298106, upload-time = "2026-01-20T20:37:23.896Z" },
+ { url = "https://files.pythonhosted.org/packages/8a/11/3dafb2a5502586f59fd49e93f5802cd5face82921b3a0f3abb5f357cb879/uuid_utils-0.14.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:191a90a6f3940d1b7322b6e6cceff4dd533c943659e0a15f788674407856a515", size = 333423, upload-time = "2026-01-20T20:37:17.828Z" },
+ { url = "https://files.pythonhosted.org/packages/7c/f2/c8987663f0cdcf4d717a36d85b5db2a5589df0a4e129aa10f16f4380ef48/uuid_utils-0.14.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4aa4525f4ad82f9d9c842f9a3703f1539c1808affbaec07bb1b842f6b8b96aa5", size = 338659, upload-time = "2026-01-20T20:37:14.286Z" },
+ { url = "https://files.pythonhosted.org/packages/d1/c8/929d81665d83f0b2ffaecb8e66c3091a50f62c7cb5b65e678bd75a96684e/uuid_utils-0.14.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cdbd82ff20147461caefc375551595ecf77ebb384e46267f128aca45a0f2cdfc", size = 467029, upload-time = "2026-01-20T20:37:08.277Z" },
+ { url = "https://files.pythonhosted.org/packages/8e/a0/27d7daa1bfed7163f4ccaf52d7d2f4ad7bb1002a85b45077938b91ee584f/uuid_utils-0.14.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eff57e8a5d540006ce73cf0841a643d445afe78ba12e75ac53a95ca2924a56be", size = 333298, upload-time = "2026-01-20T20:37:07.271Z" },
+ { url = "https://files.pythonhosted.org/packages/63/d4/acad86ce012b42ce18a12f31ee2aa3cbeeb98664f865f05f68c882945913/uuid_utils-0.14.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3fd9112ca96978361201e669729784f26c71fecc9c13a7f8a07162c31bd4d1e2", size = 359217, upload-time = "2026-01-20T20:36:59.687Z" },
+]
+
+[[package]]
+name = "xxhash"
+version = "3.6.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/02/84/30869e01909fb37a6cc7e18688ee8bf1e42d57e7e0777636bd47524c43c7/xxhash-3.6.0.tar.gz", hash = "sha256:f0162a78b13a0d7617b2845b90c763339d1f1d82bb04a4b07f4ab535cc5e05d6", size = 85160, upload-time = "2025-10-02T14:37:08.097Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/17/d4/cc2f0400e9154df4b9964249da78ebd72f318e35ccc425e9f403c392f22a/xxhash-3.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b47bbd8cf2d72797f3c2772eaaac0ded3d3af26481a26d7d7d41dc2d3c46b04a", size = 32844, upload-time = "2025-10-02T14:34:14.037Z" },
+ { url = "https://files.pythonhosted.org/packages/5e/ec/1cc11cd13e26ea8bc3cb4af4eaadd8d46d5014aebb67be3f71fb0b68802a/xxhash-3.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2b6821e94346f96db75abaa6e255706fb06ebd530899ed76d32cd99f20dc52fa", size = 30809, upload-time = "2025-10-02T14:34:15.484Z" },
+ { url = "https://files.pythonhosted.org/packages/04/5f/19fe357ea348d98ca22f456f75a30ac0916b51c753e1f8b2e0e6fb884cce/xxhash-3.6.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d0a9751f71a1a65ce3584e9cae4467651c7e70c9d31017fa57574583a4540248", size = 194665, upload-time = "2025-10-02T14:34:16.541Z" },
+ { url = "https://files.pythonhosted.org/packages/90/3b/d1f1a8f5442a5fd8beedae110c5af7604dc37349a8e16519c13c19a9a2de/xxhash-3.6.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b29ee68625ab37b04c0b40c3fafdf24d2f75ccd778333cfb698f65f6c463f62", size = 213550, upload-time = "2025-10-02T14:34:17.878Z" },
+ { url = "https://files.pythonhosted.org/packages/c4/ef/3a9b05eb527457d5db13a135a2ae1a26c80fecd624d20f3e8dcc4cb170f3/xxhash-3.6.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6812c25fe0d6c36a46ccb002f40f27ac903bf18af9f6dd8f9669cb4d176ab18f", size = 212384, upload-time = "2025-10-02T14:34:19.182Z" },
+ { url = "https://files.pythonhosted.org/packages/0f/18/ccc194ee698c6c623acbf0f8c2969811a8a4b6185af5e824cd27b9e4fd3e/xxhash-3.6.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4ccbff013972390b51a18ef1255ef5ac125c92dc9143b2d1909f59abc765540e", size = 445749, upload-time = "2025-10-02T14:34:20.659Z" },
+ { url = "https://files.pythonhosted.org/packages/a5/86/cf2c0321dc3940a7aa73076f4fd677a0fb3e405cb297ead7d864fd90847e/xxhash-3.6.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:297b7fbf86c82c550e12e8fb71968b3f033d27b874276ba3624ea868c11165a8", size = 193880, upload-time = "2025-10-02T14:34:22.431Z" },
+ { url = "https://files.pythonhosted.org/packages/82/fb/96213c8560e6f948a1ecc9a7613f8032b19ee45f747f4fca4eb31bb6d6ed/xxhash-3.6.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dea26ae1eb293db089798d3973a5fc928a18fdd97cc8801226fae705b02b14b0", size = 210912, upload-time = "2025-10-02T14:34:23.937Z" },
+ { url = "https://files.pythonhosted.org/packages/40/aa/4395e669b0606a096d6788f40dbdf2b819d6773aa290c19e6e83cbfc312f/xxhash-3.6.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7a0b169aafb98f4284f73635a8e93f0735f9cbde17bd5ec332480484241aaa77", size = 198654, upload-time = "2025-10-02T14:34:25.644Z" },
+ { url = "https://files.pythonhosted.org/packages/67/74/b044fcd6b3d89e9b1b665924d85d3f400636c23590226feb1eb09e1176ce/xxhash-3.6.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:08d45aef063a4531b785cd72de4887766d01dc8f362a515693df349fdb825e0c", size = 210867, upload-time = "2025-10-02T14:34:27.203Z" },
+ { url = "https://files.pythonhosted.org/packages/bc/fd/3ce73bf753b08cb19daee1eb14aa0d7fe331f8da9c02dd95316ddfe5275e/xxhash-3.6.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:929142361a48ee07f09121fe9e96a84950e8d4df3bb298ca5d88061969f34d7b", size = 414012, upload-time = "2025-10-02T14:34:28.409Z" },
+ { url = "https://files.pythonhosted.org/packages/ba/b3/5a4241309217c5c876f156b10778f3ab3af7ba7e3259e6d5f5c7d0129eb2/xxhash-3.6.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:51312c768403d8540487dbbfb557454cfc55589bbde6424456951f7fcd4facb3", size = 191409, upload-time = "2025-10-02T14:34:29.696Z" },
+ { url = "https://files.pythonhosted.org/packages/c0/01/99bfbc15fb9abb9a72b088c1d95219fc4782b7d01fc835bd5744d66dd0b8/xxhash-3.6.0-cp311-cp311-win32.whl", hash = "sha256:d1927a69feddc24c987b337ce81ac15c4720955b667fe9b588e02254b80446fd", size = 30574, upload-time = "2025-10-02T14:34:31.028Z" },
+ { url = "https://files.pythonhosted.org/packages/65/79/9d24d7f53819fe301b231044ea362ce64e86c74f6e8c8e51320de248b3e5/xxhash-3.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:26734cdc2d4ffe449b41d186bbeac416f704a482ed835d375a5c0cb02bc63fef", size = 31481, upload-time = "2025-10-02T14:34:32.062Z" },
+ { url = "https://files.pythonhosted.org/packages/30/4e/15cd0e3e8772071344eab2961ce83f6e485111fed8beb491a3f1ce100270/xxhash-3.6.0-cp311-cp311-win_arm64.whl", hash = "sha256:d72f67ef8bf36e05f5b6c65e8524f265bd61071471cd4cf1d36743ebeeeb06b7", size = 27861, upload-time = "2025-10-02T14:34:33.555Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/07/d9412f3d7d462347e4511181dea65e47e0d0e16e26fbee2ea86a2aefb657/xxhash-3.6.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:01362c4331775398e7bb34e3ab403bc9ee9f7c497bc7dee6272114055277dd3c", size = 32744, upload-time = "2025-10-02T14:34:34.622Z" },
+ { url = "https://files.pythonhosted.org/packages/79/35/0429ee11d035fc33abe32dca1b2b69e8c18d236547b9a9b72c1929189b9a/xxhash-3.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b7b2df81a23f8cb99656378e72501b2cb41b1827c0f5a86f87d6b06b69f9f204", size = 30816, upload-time = "2025-10-02T14:34:36.043Z" },
+ { url = "https://files.pythonhosted.org/packages/b7/f2/57eb99aa0f7d98624c0932c5b9a170e1806406cdbcdb510546634a1359e0/xxhash-3.6.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:dc94790144e66b14f67b10ac8ed75b39ca47536bf8800eb7c24b50271ea0c490", size = 194035, upload-time = "2025-10-02T14:34:37.354Z" },
+ { url = "https://files.pythonhosted.org/packages/4c/ed/6224ba353690d73af7a3f1c7cdb1fc1b002e38f783cb991ae338e1eb3d79/xxhash-3.6.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:93f107c673bccf0d592cdba077dedaf52fe7f42dcd7676eba1f6d6f0c3efffd2", size = 212914, upload-time = "2025-10-02T14:34:38.6Z" },
+ { url = "https://files.pythonhosted.org/packages/38/86/fb6b6130d8dd6b8942cc17ab4d90e223653a89aa32ad2776f8af7064ed13/xxhash-3.6.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2aa5ee3444c25b69813663c9f8067dcfaa2e126dc55e8dddf40f4d1c25d7effa", size = 212163, upload-time = "2025-10-02T14:34:39.872Z" },
+ { url = "https://files.pythonhosted.org/packages/ee/dc/e84875682b0593e884ad73b2d40767b5790d417bde603cceb6878901d647/xxhash-3.6.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f7f99123f0e1194fa59cc69ad46dbae2e07becec5df50a0509a808f90a0f03f0", size = 445411, upload-time = "2025-10-02T14:34:41.569Z" },
+ { url = "https://files.pythonhosted.org/packages/11/4f/426f91b96701ec2f37bb2b8cec664eff4f658a11f3fa9d94f0a887ea6d2b/xxhash-3.6.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:49e03e6fe2cac4a1bc64952dd250cf0dbc5ef4ebb7b8d96bce82e2de163c82a2", size = 193883, upload-time = "2025-10-02T14:34:43.249Z" },
+ { url = "https://files.pythonhosted.org/packages/53/5a/ddbb83eee8e28b778eacfc5a85c969673e4023cdeedcfcef61f36731610b/xxhash-3.6.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bd17fede52a17a4f9a7bc4472a5867cb0b160deeb431795c0e4abe158bc784e9", size = 210392, upload-time = "2025-10-02T14:34:45.042Z" },
+ { url = "https://files.pythonhosted.org/packages/1e/c2/ff69efd07c8c074ccdf0a4f36fcdd3d27363665bcdf4ba399abebe643465/xxhash-3.6.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6fb5f5476bef678f69db04f2bd1efbed3030d2aba305b0fc1773645f187d6a4e", size = 197898, upload-time = "2025-10-02T14:34:46.302Z" },
+ { url = "https://files.pythonhosted.org/packages/58/ca/faa05ac19b3b622c7c9317ac3e23954187516298a091eb02c976d0d3dd45/xxhash-3.6.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:843b52f6d88071f87eba1631b684fcb4b2068cd2180a0224122fe4ef011a9374", size = 210655, upload-time = "2025-10-02T14:34:47.571Z" },
+ { url = "https://files.pythonhosted.org/packages/d4/7a/06aa7482345480cc0cb597f5c875b11a82c3953f534394f620b0be2f700c/xxhash-3.6.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:7d14a6cfaf03b1b6f5f9790f76880601ccc7896aff7ab9cd8978a939c1eb7e0d", size = 414001, upload-time = "2025-10-02T14:34:49.273Z" },
+ { url = "https://files.pythonhosted.org/packages/23/07/63ffb386cd47029aa2916b3d2f454e6cc5b9f5c5ada3790377d5430084e7/xxhash-3.6.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:418daf3db71e1413cfe211c2f9a528456936645c17f46b5204705581a45390ae", size = 191431, upload-time = "2025-10-02T14:34:50.798Z" },
+ { url = "https://files.pythonhosted.org/packages/0f/93/14fde614cadb4ddf5e7cebf8918b7e8fac5ae7861c1875964f17e678205c/xxhash-3.6.0-cp312-cp312-win32.whl", hash = "sha256:50fc255f39428a27299c20e280d6193d8b63b8ef8028995323bf834a026b4fbb", size = 30617, upload-time = "2025-10-02T14:34:51.954Z" },
+ { url = "https://files.pythonhosted.org/packages/13/5d/0d125536cbe7565a83d06e43783389ecae0c0f2ed037b48ede185de477c0/xxhash-3.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:c0f2ab8c715630565ab8991b536ecded9416d615538be8ecddce43ccf26cbc7c", size = 31534, upload-time = "2025-10-02T14:34:53.276Z" },
+ { url = "https://files.pythonhosted.org/packages/54/85/6ec269b0952ec7e36ba019125982cf11d91256a778c7c3f98a4c5043d283/xxhash-3.6.0-cp312-cp312-win_arm64.whl", hash = "sha256:eae5c13f3bc455a3bbb68bdc513912dc7356de7e2280363ea235f71f54064829", size = 27876, upload-time = "2025-10-02T14:34:54.371Z" },
+ { url = "https://files.pythonhosted.org/packages/33/76/35d05267ac82f53ae9b0e554da7c5e281ee61f3cad44c743f0fcd354f211/xxhash-3.6.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:599e64ba7f67472481ceb6ee80fa3bd828fd61ba59fb11475572cc5ee52b89ec", size = 32738, upload-time = "2025-10-02T14:34:55.839Z" },
+ { url = "https://files.pythonhosted.org/packages/31/a8/3fbce1cd96534a95e35d5120637bf29b0d7f5d8fa2f6374e31b4156dd419/xxhash-3.6.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7d8b8aaa30fca4f16f0c84a5c8d7ddee0e25250ec2796c973775373257dde8f1", size = 30821, upload-time = "2025-10-02T14:34:57.219Z" },
+ { url = "https://files.pythonhosted.org/packages/0c/ea/d387530ca7ecfa183cb358027f1833297c6ac6098223fd14f9782cd0015c/xxhash-3.6.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d597acf8506d6e7101a4a44a5e428977a51c0fadbbfd3c39650cca9253f6e5a6", size = 194127, upload-time = "2025-10-02T14:34:59.21Z" },
+ { url = "https://files.pythonhosted.org/packages/ba/0c/71435dcb99874b09a43b8d7c54071e600a7481e42b3e3ce1eb5226a5711a/xxhash-3.6.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:858dc935963a33bc33490128edc1c12b0c14d9c7ebaa4e387a7869ecc4f3e263", size = 212975, upload-time = "2025-10-02T14:35:00.816Z" },
+ { url = "https://files.pythonhosted.org/packages/84/7a/c2b3d071e4bb4a90b7057228a99b10d51744878f4a8a6dd643c8bd897620/xxhash-3.6.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ba284920194615cb8edf73bf52236ce2e1664ccd4a38fdb543506413529cc546", size = 212241, upload-time = "2025-10-02T14:35:02.207Z" },
+ { url = "https://files.pythonhosted.org/packages/81/5f/640b6eac0128e215f177df99eadcd0f1b7c42c274ab6a394a05059694c5a/xxhash-3.6.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4b54219177f6c6674d5378bd862c6aedf64725f70dd29c472eaae154df1a2e89", size = 445471, upload-time = "2025-10-02T14:35:03.61Z" },
+ { url = "https://files.pythonhosted.org/packages/5e/1e/3c3d3ef071b051cc3abbe3721ffb8365033a172613c04af2da89d5548a87/xxhash-3.6.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:42c36dd7dbad2f5238950c377fcbf6811b1cdb1c444fab447960030cea60504d", size = 193936, upload-time = "2025-10-02T14:35:05.013Z" },
+ { url = "https://files.pythonhosted.org/packages/2c/bd/4a5f68381939219abfe1c22a9e3a5854a4f6f6f3c4983a87d255f21f2e5d/xxhash-3.6.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f22927652cba98c44639ffdc7aaf35828dccf679b10b31c4ad72a5b530a18eb7", size = 210440, upload-time = "2025-10-02T14:35:06.239Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/37/b80fe3d5cfb9faff01a02121a0f4d565eb7237e9e5fc66e73017e74dcd36/xxhash-3.6.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b45fad44d9c5c119e9c6fbf2e1c656a46dc68e280275007bbfd3d572b21426db", size = 197990, upload-time = "2025-10-02T14:35:07.735Z" },
+ { url = "https://files.pythonhosted.org/packages/d7/fd/2c0a00c97b9e18f72e1f240ad4e8f8a90fd9d408289ba9c7c495ed7dc05c/xxhash-3.6.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:6f2580ffab1a8b68ef2b901cde7e55fa8da5e4be0977c68f78fc80f3c143de42", size = 210689, upload-time = "2025-10-02T14:35:09.438Z" },
+ { url = "https://files.pythonhosted.org/packages/93/86/5dd8076a926b9a95db3206aba20d89a7fc14dd5aac16e5c4de4b56033140/xxhash-3.6.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:40c391dd3cd041ebc3ffe6f2c862f402e306eb571422e0aa918d8070ba31da11", size = 414068, upload-time = "2025-10-02T14:35:11.162Z" },
+ { url = "https://files.pythonhosted.org/packages/af/3c/0bb129170ee8f3650f08e993baee550a09593462a5cddd8e44d0011102b1/xxhash-3.6.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f205badabde7aafd1a31e8ca2a3e5a763107a71c397c4481d6a804eb5063d8bd", size = 191495, upload-time = "2025-10-02T14:35:12.971Z" },
+ { url = "https://files.pythonhosted.org/packages/e9/3a/6797e0114c21d1725e2577508e24006fd7ff1d8c0c502d3b52e45c1771d8/xxhash-3.6.0-cp313-cp313-win32.whl", hash = "sha256:2577b276e060b73b73a53042ea5bd5203d3e6347ce0d09f98500f418a9fcf799", size = 30620, upload-time = "2025-10-02T14:35:14.129Z" },
+ { url = "https://files.pythonhosted.org/packages/86/15/9bc32671e9a38b413a76d24722a2bf8784a132c043063a8f5152d390b0f9/xxhash-3.6.0-cp313-cp313-win_amd64.whl", hash = "sha256:757320d45d2fbcce8f30c42a6b2f47862967aea7bf458b9625b4bbe7ee390392", size = 31542, upload-time = "2025-10-02T14:35:15.21Z" },
+ { url = "https://files.pythonhosted.org/packages/39/c5/cc01e4f6188656e56112d6a8e0dfe298a16934b8c47a247236549a3f7695/xxhash-3.6.0-cp313-cp313-win_arm64.whl", hash = "sha256:457b8f85dec5825eed7b69c11ae86834a018b8e3df5e77783c999663da2f96d6", size = 27880, upload-time = "2025-10-02T14:35:16.315Z" },
+ { url = "https://files.pythonhosted.org/packages/f3/30/25e5321c8732759e930c555176d37e24ab84365482d257c3b16362235212/xxhash-3.6.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a42e633d75cdad6d625434e3468126c73f13f7584545a9cf34e883aa1710e702", size = 32956, upload-time = "2025-10-02T14:35:17.413Z" },
+ { url = "https://files.pythonhosted.org/packages/9f/3c/0573299560d7d9f8ab1838f1efc021a280b5ae5ae2e849034ef3dee18810/xxhash-3.6.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:568a6d743219e717b07b4e03b0a828ce593833e498c3b64752e0f5df6bfe84db", size = 31072, upload-time = "2025-10-02T14:35:18.844Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/1c/52d83a06e417cd9d4137722693424885cc9878249beb3a7c829e74bf7ce9/xxhash-3.6.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bec91b562d8012dae276af8025a55811b875baace6af510412a5e58e3121bc54", size = 196409, upload-time = "2025-10-02T14:35:20.31Z" },
+ { url = "https://files.pythonhosted.org/packages/e3/8e/c6d158d12a79bbd0b878f8355432075fc82759e356ab5a111463422a239b/xxhash-3.6.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:78e7f2f4c521c30ad5e786fdd6bae89d47a32672a80195467b5de0480aa97b1f", size = 215736, upload-time = "2025-10-02T14:35:21.616Z" },
+ { url = "https://files.pythonhosted.org/packages/bc/68/c4c80614716345d55071a396cf03d06e34b5f4917a467faf43083c995155/xxhash-3.6.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3ed0df1b11a79856df5ffcab572cbd6b9627034c1c748c5566fa79df9048a7c5", size = 214833, upload-time = "2025-10-02T14:35:23.32Z" },
+ { url = "https://files.pythonhosted.org/packages/7e/e9/ae27c8ffec8b953efa84c7c4a6c6802c263d587b9fc0d6e7cea64e08c3af/xxhash-3.6.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0e4edbfc7d420925b0dd5e792478ed393d6e75ff8fc219a6546fb446b6a417b1", size = 448348, upload-time = "2025-10-02T14:35:25.111Z" },
+ { url = "https://files.pythonhosted.org/packages/d7/6b/33e21afb1b5b3f46b74b6bd1913639066af218d704cc0941404ca717fc57/xxhash-3.6.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fba27a198363a7ef87f8c0f6b171ec36b674fe9053742c58dd7e3201c1ab30ee", size = 196070, upload-time = "2025-10-02T14:35:26.586Z" },
+ { url = "https://files.pythonhosted.org/packages/96/b6/fcabd337bc5fa624e7203aa0fa7d0c49eed22f72e93229431752bddc83d9/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:794fe9145fe60191c6532fa95063765529770edcdd67b3d537793e8004cabbfd", size = 212907, upload-time = "2025-10-02T14:35:28.087Z" },
+ { url = "https://files.pythonhosted.org/packages/4b/d3/9ee6160e644d660fcf176c5825e61411c7f62648728f69c79ba237250143/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:6105ef7e62b5ac73a837778efc331a591d8442f8ef5c7e102376506cb4ae2729", size = 200839, upload-time = "2025-10-02T14:35:29.857Z" },
+ { url = "https://files.pythonhosted.org/packages/0d/98/e8de5baa5109394baf5118f5e72ab21a86387c4f89b0e77ef3e2f6b0327b/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:f01375c0e55395b814a679b3eea205db7919ac2af213f4a6682e01220e5fe292", size = 213304, upload-time = "2025-10-02T14:35:31.222Z" },
+ { url = "https://files.pythonhosted.org/packages/7b/1d/71056535dec5c3177eeb53e38e3d367dd1d16e024e63b1cee208d572a033/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:d706dca2d24d834a4661619dcacf51a75c16d65985718d6a7d73c1eeeb903ddf", size = 416930, upload-time = "2025-10-02T14:35:32.517Z" },
+ { url = "https://files.pythonhosted.org/packages/dc/6c/5cbde9de2cd967c322e651c65c543700b19e7ae3e0aae8ece3469bf9683d/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5f059d9faeacd49c0215d66f4056e1326c80503f51a1532ca336a385edadd033", size = 193787, upload-time = "2025-10-02T14:35:33.827Z" },
+ { url = "https://files.pythonhosted.org/packages/19/fa/0172e350361d61febcea941b0cc541d6e6c8d65d153e85f850a7b256ff8a/xxhash-3.6.0-cp313-cp313t-win32.whl", hash = "sha256:1244460adc3a9be84731d72b8e80625788e5815b68da3da8b83f78115a40a7ec", size = 30916, upload-time = "2025-10-02T14:35:35.107Z" },
+ { url = "https://files.pythonhosted.org/packages/ad/e6/e8cf858a2b19d6d45820f072eff1bea413910592ff17157cabc5f1227a16/xxhash-3.6.0-cp313-cp313t-win_amd64.whl", hash = "sha256:b1e420ef35c503869c4064f4a2f2b08ad6431ab7b229a05cce39d74268bca6b8", size = 31799, upload-time = "2025-10-02T14:35:36.165Z" },
+ { url = "https://files.pythonhosted.org/packages/56/15/064b197e855bfb7b343210e82490ae672f8bc7cdf3ddb02e92f64304ee8a/xxhash-3.6.0-cp313-cp313t-win_arm64.whl", hash = "sha256:ec44b73a4220623235f67a996c862049f375df3b1052d9899f40a6382c32d746", size = 28044, upload-time = "2025-10-02T14:35:37.195Z" },
+ { url = "https://files.pythonhosted.org/packages/7e/5e/0138bc4484ea9b897864d59fce9be9086030825bc778b76cb5a33a906d37/xxhash-3.6.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:a40a3d35b204b7cc7643cbcf8c9976d818cb47befcfac8bbefec8038ac363f3e", size = 32754, upload-time = "2025-10-02T14:35:38.245Z" },
+ { url = "https://files.pythonhosted.org/packages/18/d7/5dac2eb2ec75fd771957a13e5dda560efb2176d5203f39502a5fc571f899/xxhash-3.6.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a54844be970d3fc22630b32d515e79a90d0a3ddb2644d8d7402e3c4c8da61405", size = 30846, upload-time = "2025-10-02T14:35:39.6Z" },
+ { url = "https://files.pythonhosted.org/packages/fe/71/8bc5be2bb00deb5682e92e8da955ebe5fa982da13a69da5a40a4c8db12fb/xxhash-3.6.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:016e9190af8f0a4e3741343777710e3d5717427f175adfdc3e72508f59e2a7f3", size = 194343, upload-time = "2025-10-02T14:35:40.69Z" },
+ { url = "https://files.pythonhosted.org/packages/e7/3b/52badfb2aecec2c377ddf1ae75f55db3ba2d321c5e164f14461c90837ef3/xxhash-3.6.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4f6f72232f849eb9d0141e2ebe2677ece15adfd0fa599bc058aad83c714bb2c6", size = 213074, upload-time = "2025-10-02T14:35:42.29Z" },
+ { url = "https://files.pythonhosted.org/packages/a2/2b/ae46b4e9b92e537fa30d03dbc19cdae57ed407e9c26d163895e968e3de85/xxhash-3.6.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:63275a8aba7865e44b1813d2177e0f5ea7eadad3dd063a21f7cf9afdc7054063", size = 212388, upload-time = "2025-10-02T14:35:43.929Z" },
+ { url = "https://files.pythonhosted.org/packages/f5/80/49f88d3afc724b4ac7fbd664c8452d6db51b49915be48c6982659e0e7942/xxhash-3.6.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cd01fa2aa00d8b017c97eb46b9a794fbdca53fc14f845f5a328c71254b0abb7", size = 445614, upload-time = "2025-10-02T14:35:45.216Z" },
+ { url = "https://files.pythonhosted.org/packages/ed/ba/603ce3961e339413543d8cd44f21f2c80e2a7c5cfe692a7b1f2cccf58f3c/xxhash-3.6.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0226aa89035b62b6a86d3c68df4d7c1f47a342b8683da2b60cedcddb46c4d95b", size = 194024, upload-time = "2025-10-02T14:35:46.959Z" },
+ { url = "https://files.pythonhosted.org/packages/78/d1/8e225ff7113bf81545cfdcd79eef124a7b7064a0bba53605ff39590b95c2/xxhash-3.6.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c6e193e9f56e4ca4923c61238cdaced324f0feac782544eb4c6d55ad5cc99ddd", size = 210541, upload-time = "2025-10-02T14:35:48.301Z" },
+ { url = "https://files.pythonhosted.org/packages/6f/58/0f89d149f0bad89def1a8dd38feb50ccdeb643d9797ec84707091d4cb494/xxhash-3.6.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:9176dcaddf4ca963d4deb93866d739a343c01c969231dbe21680e13a5d1a5bf0", size = 198305, upload-time = "2025-10-02T14:35:49.584Z" },
+ { url = "https://files.pythonhosted.org/packages/11/38/5eab81580703c4df93feb5f32ff8fa7fe1e2c51c1f183ee4e48d4bb9d3d7/xxhash-3.6.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:c1ce4009c97a752e682b897aa99aef84191077a9433eb237774689f14f8ec152", size = 210848, upload-time = "2025-10-02T14:35:50.877Z" },
+ { url = "https://files.pythonhosted.org/packages/5e/6b/953dc4b05c3ce678abca756416e4c130d2382f877a9c30a20d08ee6a77c0/xxhash-3.6.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:8cb2f4f679b01513b7adbb9b1b2f0f9cdc31b70007eaf9d59d0878809f385b11", size = 414142, upload-time = "2025-10-02T14:35:52.15Z" },
+ { url = "https://files.pythonhosted.org/packages/08/a9/238ec0d4e81a10eb5026d4a6972677cbc898ba6c8b9dbaec12ae001b1b35/xxhash-3.6.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:653a91d7c2ab54a92c19ccf43508b6a555440b9be1bc8be553376778be7f20b5", size = 191547, upload-time = "2025-10-02T14:35:53.547Z" },
+ { url = "https://files.pythonhosted.org/packages/f1/ee/3cf8589e06c2164ac77c3bf0aa127012801128f1feebf2a079272da5737c/xxhash-3.6.0-cp314-cp314-win32.whl", hash = "sha256:a756fe893389483ee8c394d06b5ab765d96e68fbbfe6fde7aa17e11f5720559f", size = 31214, upload-time = "2025-10-02T14:35:54.746Z" },
+ { url = "https://files.pythonhosted.org/packages/02/5d/a19552fbc6ad4cb54ff953c3908bbc095f4a921bc569433d791f755186f1/xxhash-3.6.0-cp314-cp314-win_amd64.whl", hash = "sha256:39be8e4e142550ef69629c9cd71b88c90e9a5db703fecbcf265546d9536ca4ad", size = 32290, upload-time = "2025-10-02T14:35:55.791Z" },
+ { url = "https://files.pythonhosted.org/packages/b1/11/dafa0643bc30442c887b55baf8e73353a344ee89c1901b5a5c54a6c17d39/xxhash-3.6.0-cp314-cp314-win_arm64.whl", hash = "sha256:25915e6000338999236f1eb68a02a32c3275ac338628a7eaa5a269c401995679", size = 28795, upload-time = "2025-10-02T14:35:57.162Z" },
+ { url = "https://files.pythonhosted.org/packages/2c/db/0e99732ed7f64182aef4a6fb145e1a295558deec2a746265dcdec12d191e/xxhash-3.6.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:c5294f596a9017ca5a3e3f8884c00b91ab2ad2933cf288f4923c3fd4346cf3d4", size = 32955, upload-time = "2025-10-02T14:35:58.267Z" },
+ { url = "https://files.pythonhosted.org/packages/55/f4/2a7c3c68e564a099becfa44bb3d398810cc0ff6749b0d3cb8ccb93f23c14/xxhash-3.6.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1cf9dcc4ab9cff01dfbba78544297a3a01dafd60f3bde4e2bfd016cf7e4ddc67", size = 31072, upload-time = "2025-10-02T14:35:59.382Z" },
+ { url = "https://files.pythonhosted.org/packages/c6/d9/72a29cddc7250e8a5819dad5d466facb5dc4c802ce120645630149127e73/xxhash-3.6.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:01262da8798422d0685f7cef03b2bd3f4f46511b02830861df548d7def4402ad", size = 196579, upload-time = "2025-10-02T14:36:00.838Z" },
+ { url = "https://files.pythonhosted.org/packages/63/93/b21590e1e381040e2ca305a884d89e1c345b347404f7780f07f2cdd47ef4/xxhash-3.6.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:51a73fb7cb3a3ead9f7a8b583ffd9b8038e277cdb8cb87cf890e88b3456afa0b", size = 215854, upload-time = "2025-10-02T14:36:02.207Z" },
+ { url = "https://files.pythonhosted.org/packages/ce/b8/edab8a7d4fa14e924b29be877d54155dcbd8b80be85ea00d2be3413a9ed4/xxhash-3.6.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b9c6df83594f7df8f7f708ce5ebeacfc69f72c9fbaaababf6cf4758eaada0c9b", size = 214965, upload-time = "2025-10-02T14:36:03.507Z" },
+ { url = "https://files.pythonhosted.org/packages/27/67/dfa980ac7f0d509d54ea0d5a486d2bb4b80c3f1bb22b66e6a05d3efaf6c0/xxhash-3.6.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:627f0af069b0ea56f312fd5189001c24578868643203bca1abbc2c52d3a6f3ca", size = 448484, upload-time = "2025-10-02T14:36:04.828Z" },
+ { url = "https://files.pythonhosted.org/packages/8c/63/8ffc2cc97e811c0ca5d00ab36604b3ea6f4254f20b7bc658ca825ce6c954/xxhash-3.6.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aa912c62f842dfd013c5f21a642c9c10cd9f4c4e943e0af83618b4a404d9091a", size = 196162, upload-time = "2025-10-02T14:36:06.182Z" },
+ { url = "https://files.pythonhosted.org/packages/4b/77/07f0e7a3edd11a6097e990f6e5b815b6592459cb16dae990d967693e6ea9/xxhash-3.6.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:b465afd7909db30168ab62afe40b2fcf79eedc0b89a6c0ab3123515dc0df8b99", size = 213007, upload-time = "2025-10-02T14:36:07.733Z" },
+ { url = "https://files.pythonhosted.org/packages/ae/d8/bc5fa0d152837117eb0bef6f83f956c509332ce133c91c63ce07ee7c4873/xxhash-3.6.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:a881851cf38b0a70e7c4d3ce81fc7afd86fbc2a024f4cfb2a97cf49ce04b75d3", size = 200956, upload-time = "2025-10-02T14:36:09.106Z" },
+ { url = "https://files.pythonhosted.org/packages/26/a5/d749334130de9411783873e9b98ecc46688dad5db64ca6e04b02acc8b473/xxhash-3.6.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:9b3222c686a919a0f3253cfc12bb118b8b103506612253b5baeaac10d8027cf6", size = 213401, upload-time = "2025-10-02T14:36:10.585Z" },
+ { url = "https://files.pythonhosted.org/packages/89/72/abed959c956a4bfc72b58c0384bb7940663c678127538634d896b1195c10/xxhash-3.6.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:c5aa639bc113e9286137cec8fadc20e9cd732b2cc385c0b7fa673b84fc1f2a93", size = 417083, upload-time = "2025-10-02T14:36:12.276Z" },
+ { url = "https://files.pythonhosted.org/packages/0c/b3/62fd2b586283b7d7d665fb98e266decadf31f058f1cf6c478741f68af0cb/xxhash-3.6.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5c1343d49ac102799905e115aee590183c3921d475356cb24b4de29a4bc56518", size = 193913, upload-time = "2025-10-02T14:36:14.025Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/9a/c19c42c5b3f5a4aad748a6d5b4f23df3bed7ee5445accc65a0fb3ff03953/xxhash-3.6.0-cp314-cp314t-win32.whl", hash = "sha256:5851f033c3030dd95c086b4a36a2683c2ff4a799b23af60977188b057e467119", size = 31586, upload-time = "2025-10-02T14:36:15.603Z" },
+ { url = "https://files.pythonhosted.org/packages/03/d6/4cc450345be9924fd5dc8c590ceda1db5b43a0a889587b0ae81a95511360/xxhash-3.6.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0444e7967dac37569052d2409b00a8860c2135cff05502df4da80267d384849f", size = 32526, upload-time = "2025-10-02T14:36:16.708Z" },
+ { url = "https://files.pythonhosted.org/packages/0f/c9/7243eb3f9eaabd1a88a5a5acadf06df2d83b100c62684b7425c6a11bcaa8/xxhash-3.6.0-cp314-cp314t-win_arm64.whl", hash = "sha256:bb79b1e63f6fd84ec778a4b1916dfe0a7c3fdb986c06addd5db3a0d413819d95", size = 28898, upload-time = "2025-10-02T14:36:17.843Z" },
+ { url = "https://files.pythonhosted.org/packages/93/1e/8aec23647a34a249f62e2398c42955acd9b4c6ed5cf08cbea94dc46f78d2/xxhash-3.6.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0f7b7e2ec26c1666ad5fc9dbfa426a6a3367ceaf79db5dd76264659d509d73b0", size = 30662, upload-time = "2025-10-02T14:37:01.743Z" },
+ { url = "https://files.pythonhosted.org/packages/b8/0b/b14510b38ba91caf43006209db846a696ceea6a847a0c9ba0a5b1adc53d6/xxhash-3.6.0-pp311-pypy311_pp73-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5dc1e14d14fa0f5789ec29a7062004b5933964bb9b02aae6622b8f530dc40296", size = 41056, upload-time = "2025-10-02T14:37:02.879Z" },
+ { url = "https://files.pythonhosted.org/packages/50/55/15a7b8a56590e66ccd374bbfa3f9ffc45b810886c8c3b614e3f90bd2367c/xxhash-3.6.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:881b47fc47e051b37d94d13e7455131054b56749b91b508b0907eb07900d1c13", size = 36251, upload-time = "2025-10-02T14:37:04.44Z" },
+ { url = "https://files.pythonhosted.org/packages/62/b2/5ac99a041a29e58e95f907876b04f7067a0242cb85b5f39e726153981503/xxhash-3.6.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c6dc31591899f5e5666f04cc2e529e69b4072827085c1ef15294d91a004bc1bd", size = 32481, upload-time = "2025-10-02T14:37:05.869Z" },
+ { url = "https://files.pythonhosted.org/packages/7b/d9/8d95e906764a386a3d3b596f3c68bb63687dfca806373509f51ce8eea81f/xxhash-3.6.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:15e0dac10eb9309508bfc41f7f9deaa7755c69e35af835db9cb10751adebc35d", size = 31565, upload-time = "2025-10-02T14:37:06.966Z" },
+]
+
+[[package]]
+name = "yarl"
+version = "1.22.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "idna" },
+ { name = "multidict" },
+ { name = "propcache" },
+]
+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/4d/27/5ab13fc84c76a0250afd3d26d5936349a35be56ce5785447d6c423b26d92/yarl-1.22.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1ab72135b1f2db3fed3997d7e7dc1b80573c67138023852b6efb336a5eae6511", size = 141607, upload-time = "2025-10-06T14:09:16.298Z" },
+ { url = "https://files.pythonhosted.org/packages/6a/a1/d065d51d02dc02ce81501d476b9ed2229d9a990818332242a882d5d60340/yarl-1.22.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:669930400e375570189492dc8d8341301578e8493aec04aebc20d4717f899dd6", size = 94027, upload-time = "2025-10-06T14:09:17.786Z" },
+ { url = "https://files.pythonhosted.org/packages/c1/da/8da9f6a53f67b5106ffe902c6fa0164e10398d4e150d85838b82f424072a/yarl-1.22.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:792a2af6d58177ef7c19cbf0097aba92ca1b9cb3ffdd9c7470e156c8f9b5e028", size = 94963, upload-time = "2025-10-06T14:09:19.662Z" },
+ { url = "https://files.pythonhosted.org/packages/68/fe/2c1f674960c376e29cb0bec1249b117d11738db92a6ccc4a530b972648db/yarl-1.22.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3ea66b1c11c9150f1372f69afb6b8116f2dd7286f38e14ea71a44eee9ec51b9d", size = 368406, upload-time = "2025-10-06T14:09:21.402Z" },
+ { url = "https://files.pythonhosted.org/packages/95/26/812a540e1c3c6418fec60e9bbd38e871eaba9545e94fa5eff8f4a8e28e1e/yarl-1.22.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3e2daa88dc91870215961e96a039ec73e4937da13cf77ce17f9cad0c18df3503", size = 336581, upload-time = "2025-10-06T14:09:22.98Z" },
+ { url = "https://files.pythonhosted.org/packages/0b/f5/5777b19e26fdf98563985e481f8be3d8a39f8734147a6ebf459d0dab5a6b/yarl-1.22.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ba440ae430c00eee41509353628600212112cd5018d5def7e9b05ea7ac34eb65", size = 388924, upload-time = "2025-10-06T14:09:24.655Z" },
+ { url = "https://files.pythonhosted.org/packages/86/08/24bd2477bd59c0bbd994fe1d93b126e0472e4e3df5a96a277b0a55309e89/yarl-1.22.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e6438cc8f23a9c1478633d216b16104a586b9761db62bfacb6425bac0a36679e", size = 392890, upload-time = "2025-10-06T14:09:26.617Z" },
+ { url = "https://files.pythonhosted.org/packages/46/00/71b90ed48e895667ecfb1eaab27c1523ee2fa217433ed77a73b13205ca4b/yarl-1.22.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c52a6e78aef5cf47a98ef8e934755abf53953379b7d53e68b15ff4420e6683d", size = 365819, upload-time = "2025-10-06T14:09:28.544Z" },
+ { url = "https://files.pythonhosted.org/packages/30/2d/f715501cae832651d3282387c6a9236cd26bd00d0ff1e404b3dc52447884/yarl-1.22.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3b06bcadaac49c70f4c88af4ffcfbe3dc155aab3163e75777818092478bcbbe7", size = 363601, upload-time = "2025-10-06T14:09:30.568Z" },
+ { url = "https://files.pythonhosted.org/packages/f8/f9/a678c992d78e394e7126ee0b0e4e71bd2775e4334d00a9278c06a6cce96a/yarl-1.22.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:6944b2dc72c4d7f7052683487e3677456050ff77fcf5e6204e98caf785ad1967", size = 358072, upload-time = "2025-10-06T14:09:32.528Z" },
+ { url = "https://files.pythonhosted.org/packages/2c/d1/b49454411a60edb6fefdcad4f8e6dbba7d8019e3a508a1c5836cba6d0781/yarl-1.22.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:d5372ca1df0f91a86b047d1277c2aaf1edb32d78bbcefffc81b40ffd18f027ed", size = 385311, upload-time = "2025-10-06T14:09:34.634Z" },
+ { url = "https://files.pythonhosted.org/packages/87/e5/40d7a94debb8448c7771a916d1861d6609dddf7958dc381117e7ba36d9e8/yarl-1.22.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:51af598701f5299012b8416486b40fceef8c26fc87dc6d7d1f6fc30609ea0aa6", size = 381094, upload-time = "2025-10-06T14:09:36.268Z" },
+ { url = "https://files.pythonhosted.org/packages/35/d8/611cc282502381ad855448643e1ad0538957fc82ae83dfe7762c14069e14/yarl-1.22.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b266bd01fedeffeeac01a79ae181719ff848a5a13ce10075adbefc8f1daee70e", size = 370944, upload-time = "2025-10-06T14:09:37.872Z" },
+ { url = "https://files.pythonhosted.org/packages/2d/df/fadd00fb1c90e1a5a8bd731fa3d3de2e165e5a3666a095b04e31b04d9cb6/yarl-1.22.0-cp311-cp311-win32.whl", hash = "sha256:a9b1ba5610a4e20f655258d5a1fdc7ebe3d837bb0e45b581398b99eb98b1f5ca", size = 81804, upload-time = "2025-10-06T14:09:39.359Z" },
+ { url = "https://files.pythonhosted.org/packages/b5/f7/149bb6f45f267cb5c074ac40c01c6b3ea6d8a620d34b337f6321928a1b4d/yarl-1.22.0-cp311-cp311-win_amd64.whl", hash = "sha256:078278b9b0b11568937d9509b589ee83ef98ed6d561dfe2020e24a9fd08eaa2b", size = 86858, upload-time = "2025-10-06T14:09:41.068Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/13/88b78b93ad3f2f0b78e13bfaaa24d11cbc746e93fe76d8c06bf139615646/yarl-1.22.0-cp311-cp311-win_arm64.whl", hash = "sha256:b6a6f620cfe13ccec221fa312139135166e47ae169f8253f72a0abc0dae94376", size = 81637, upload-time = "2025-10-06T14:09:42.712Z" },
+ { 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" },
+ { url = "https://files.pythonhosted.org/packages/a7/bc/315a56aca762d44a6aaaf7ad253f04d996cb6b27bad34410f82d76ea8038/yarl-1.22.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3d7a87a78d46a2e3d5b72587ac14b4c16952dd0887dbb051451eceac774411e", size = 372080, upload-time = "2025-10-06T14:11:20.996Z" },
+ { url = "https://files.pythonhosted.org/packages/3f/3f/08e9b826ec2e099ea6e7c69a61272f4f6da62cb5b1b63590bb80ca2e4a40/yarl-1.22.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:852863707010316c973162e703bddabec35e8757e67fcb8ad58829de1ebc8590", size = 338696, upload-time = "2025-10-06T14:11:22.847Z" },
+ { url = "https://files.pythonhosted.org/packages/e3/9f/90360108e3b32bd76789088e99538febfea24a102380ae73827f62073543/yarl-1.22.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:131a085a53bfe839a477c0845acf21efc77457ba2bcf5899618136d64f3303a2", size = 387121, upload-time = "2025-10-06T14:11:24.889Z" },
+ { url = "https://files.pythonhosted.org/packages/98/92/ab8d4657bd5b46a38094cfaea498f18bb70ce6b63508fd7e909bd1f93066/yarl-1.22.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:078a8aefd263f4d4f923a9677b942b445a2be970ca24548a8102689a3a8ab8da", size = 394080, upload-time = "2025-10-06T14:11:27.307Z" },
+ { url = "https://files.pythonhosted.org/packages/f5/e7/d8c5a7752fef68205296201f8ec2bf718f5c805a7a7e9880576c67600658/yarl-1.22.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bca03b91c323036913993ff5c738d0842fc9c60c4648e5c8d98331526df89784", size = 372661, upload-time = "2025-10-06T14:11:29.387Z" },
+ { url = "https://files.pythonhosted.org/packages/b6/2e/f4d26183c8db0bb82d491b072f3127fb8c381a6206a3a56332714b79b751/yarl-1.22.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:68986a61557d37bb90d3051a45b91fa3d5c516d177dfc6dd6f2f436a07ff2b6b", size = 364645, upload-time = "2025-10-06T14:11:31.423Z" },
+ { url = "https://files.pythonhosted.org/packages/80/7c/428e5812e6b87cd00ee8e898328a62c95825bf37c7fa87f0b6bb2ad31304/yarl-1.22.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:4792b262d585ff0dff6bcb787f8492e40698443ec982a3568c2096433660c694", size = 355361, upload-time = "2025-10-06T14:11:33.055Z" },
+ { url = "https://files.pythonhosted.org/packages/ec/2a/249405fd26776f8b13c067378ef4d7dd49c9098d1b6457cdd152a99e96a9/yarl-1.22.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:ebd4549b108d732dba1d4ace67614b9545b21ece30937a63a65dd34efa19732d", size = 381451, upload-time = "2025-10-06T14:11:35.136Z" },
+ { url = "https://files.pythonhosted.org/packages/67/a8/fb6b1adbe98cf1e2dd9fad71003d3a63a1bc22459c6e15f5714eb9323b93/yarl-1.22.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f87ac53513d22240c7d59203f25cc3beac1e574c6cd681bbfd321987b69f95fd", size = 383814, upload-time = "2025-10-06T14:11:37.094Z" },
+ { url = "https://files.pythonhosted.org/packages/d9/f9/3aa2c0e480fb73e872ae2814c43bc1e734740bb0d54e8cb2a95925f98131/yarl-1.22.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:22b029f2881599e2f1b06f8f1db2ee63bd309e2293ba2d566e008ba12778b8da", size = 370799, upload-time = "2025-10-06T14:11:38.83Z" },
+ { url = "https://files.pythonhosted.org/packages/50/3c/af9dba3b8b5eeb302f36f16f92791f3ea62e3f47763406abf6d5a4a3333b/yarl-1.22.0-cp314-cp314-win32.whl", hash = "sha256:6a635ea45ba4ea8238463b4f7d0e721bad669f80878b7bfd1f89266e2ae63da2", size = 82990, upload-time = "2025-10-06T14:11:40.624Z" },
+ { url = "https://files.pythonhosted.org/packages/ac/30/ac3a0c5bdc1d6efd1b41fa24d4897a4329b3b1e98de9449679dd327af4f0/yarl-1.22.0-cp314-cp314-win_amd64.whl", hash = "sha256:0d6e6885777af0f110b0e5d7e5dda8b704efed3894da26220b7f3d887b839a79", size = 88292, upload-time = "2025-10-06T14:11:42.578Z" },
+ { url = "https://files.pythonhosted.org/packages/df/0a/227ab4ff5b998a1b7410abc7b46c9b7a26b0ca9e86c34ba4b8d8bc7c63d5/yarl-1.22.0-cp314-cp314-win_arm64.whl", hash = "sha256:8218f4e98d3c10d683584cb40f0424f4b9fd6e95610232dd75e13743b070ee33", size = 82888, upload-time = "2025-10-06T14:11:44.863Z" },
+ { url = "https://files.pythonhosted.org/packages/06/5e/a15eb13db90abd87dfbefb9760c0f3f257ac42a5cac7e75dbc23bed97a9f/yarl-1.22.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:45c2842ff0e0d1b35a6bf1cd6c690939dacb617a70827f715232b2e0494d55d1", size = 146223, upload-time = "2025-10-06T14:11:46.796Z" },
+ { url = "https://files.pythonhosted.org/packages/18/82/9665c61910d4d84f41a5bf6837597c89e665fa88aa4941080704645932a9/yarl-1.22.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:d947071e6ebcf2e2bee8fce76e10faca8f7a14808ca36a910263acaacef08eca", size = 95981, upload-time = "2025-10-06T14:11:48.845Z" },
+ { url = "https://files.pythonhosted.org/packages/5d/9a/2f65743589809af4d0a6d3aa749343c4b5f4c380cc24a8e94a3c6625a808/yarl-1.22.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:334b8721303e61b00019474cc103bdac3d7b1f65e91f0bfedeec2d56dfe74b53", size = 97303, upload-time = "2025-10-06T14:11:50.897Z" },
+ { url = "https://files.pythonhosted.org/packages/b0/ab/5b13d3e157505c43c3b43b5a776cbf7b24a02bc4cccc40314771197e3508/yarl-1.22.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e7ce67c34138a058fd092f67d07a72b8e31ff0c9236e751957465a24b28910c", size = 361820, upload-time = "2025-10-06T14:11:52.549Z" },
+ { url = "https://files.pythonhosted.org/packages/fb/76/242a5ef4677615cf95330cfc1b4610e78184400699bdda0acb897ef5e49a/yarl-1.22.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d77e1b2c6d04711478cb1c4ab90db07f1609ccf06a287d5607fcd90dc9863acf", size = 323203, upload-time = "2025-10-06T14:11:54.225Z" },
+ { url = "https://files.pythonhosted.org/packages/8c/96/475509110d3f0153b43d06164cf4195c64d16999e0c7e2d8a099adcd6907/yarl-1.22.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4647674b6150d2cae088fc07de2738a84b8bcedebef29802cf0b0a82ab6face", size = 363173, upload-time = "2025-10-06T14:11:56.069Z" },
+ { url = "https://files.pythonhosted.org/packages/c9/66/59db471aecfbd559a1fd48aedd954435558cd98c7d0da8b03cc6c140a32c/yarl-1.22.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:efb07073be061c8f79d03d04139a80ba33cbd390ca8f0297aae9cce6411e4c6b", size = 373562, upload-time = "2025-10-06T14:11:58.783Z" },
+ { url = "https://files.pythonhosted.org/packages/03/1f/c5d94abc91557384719da10ff166b916107c1b45e4d0423a88457071dd88/yarl-1.22.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e51ac5435758ba97ad69617e13233da53908beccc6cfcd6c34bbed8dcbede486", size = 339828, upload-time = "2025-10-06T14:12:00.686Z" },
+ { url = "https://files.pythonhosted.org/packages/5f/97/aa6a143d3afba17b6465733681c70cf175af89f76ec8d9286e08437a7454/yarl-1.22.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:33e32a0dd0c8205efa8e83d04fc9f19313772b78522d1bdc7d9aed706bfd6138", size = 347551, upload-time = "2025-10-06T14:12:02.628Z" },
+ { url = "https://files.pythonhosted.org/packages/43/3c/45a2b6d80195959239a7b2a8810506d4eea5487dce61c2a3393e7fc3c52e/yarl-1.22.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:bf4a21e58b9cde0e401e683ebd00f6ed30a06d14e93f7c8fd059f8b6e8f87b6a", size = 334512, upload-time = "2025-10-06T14:12:04.871Z" },
+ { url = "https://files.pythonhosted.org/packages/86/a0/c2ab48d74599c7c84cb104ebd799c5813de252bea0f360ffc29d270c2caa/yarl-1.22.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:e4b582bab49ac33c8deb97e058cd67c2c50dac0dd134874106d9c774fd272529", size = 352400, upload-time = "2025-10-06T14:12:06.624Z" },
+ { url = "https://files.pythonhosted.org/packages/32/75/f8919b2eafc929567d3d8411f72bdb1a2109c01caaab4ebfa5f8ffadc15b/yarl-1.22.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:0b5bcc1a9c4839e7e30b7b30dd47fe5e7e44fb7054ec29b5bb8d526aa1041093", size = 357140, upload-time = "2025-10-06T14:12:08.362Z" },
+ { url = "https://files.pythonhosted.org/packages/cf/72/6a85bba382f22cf78add705d8c3731748397d986e197e53ecc7835e76de7/yarl-1.22.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c0232bce2170103ec23c454e54a57008a9a72b5d1c3105dc2496750da8cfa47c", size = 341473, upload-time = "2025-10-06T14:12:10.994Z" },
+ { url = "https://files.pythonhosted.org/packages/35/18/55e6011f7c044dc80b98893060773cefcfdbf60dfefb8cb2f58b9bacbd83/yarl-1.22.0-cp314-cp314t-win32.whl", hash = "sha256:8009b3173bcd637be650922ac455946197d858b3630b6d8787aa9e5c4564533e", size = 89056, upload-time = "2025-10-06T14:12:13.317Z" },
+ { url = "https://files.pythonhosted.org/packages/f9/86/0f0dccb6e59a9e7f122c5afd43568b1d31b8ab7dda5f1b01fb5c7025c9a9/yarl-1.22.0-cp314-cp314t-win_amd64.whl", hash = "sha256:9fb17ea16e972c63d25d4a97f016d235c78dd2344820eb35bc034bc32012ee27", size = 96292, upload-time = "2025-10-06T14:12:15.398Z" },
+ { url = "https://files.pythonhosted.org/packages/48/b7/503c98092fb3b344a179579f55814b613c1fbb1c23b3ec14a7b008a66a6e/yarl-1.22.0-cp314-cp314t-win_arm64.whl", hash = "sha256:9f6d73c1436b934e3f01df1e1b21ff765cd1d28c77dfb9ace207f746d4610ee1", size = 85171, upload-time = "2025-10-06T14:12:16.935Z" },
+ { url = "https://files.pythonhosted.org/packages/73/ae/b48f95715333080afb75a4504487cbe142cae1268afc482d06692d605ae6/yarl-1.22.0-py3-none-any.whl", hash = "sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff", size = 46814, upload-time = "2025-10-06T14:12:53.872Z" },
+]
+
+[[package]]
+name = "zstandard"
+version = "0.25.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/fd/aa/3e0508d5a5dd96529cdc5a97011299056e14c6505b678fd58938792794b1/zstandard-0.25.0.tar.gz", hash = "sha256:7713e1179d162cf5c7906da876ec2ccb9c3a9dcbdffef0cc7f70c3667a205f0b", size = 711513, upload-time = "2025-09-14T22:15:54.002Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/2a/83/c3ca27c363d104980f1c9cee1101cc8ba724ac8c28a033ede6aab89585b1/zstandard-0.25.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:933b65d7680ea337180733cf9e87293cc5500cc0eb3fc8769f4d3c88d724ec5c", size = 795254, upload-time = "2025-09-14T22:16:26.137Z" },
+ { url = "https://files.pythonhosted.org/packages/ac/4d/e66465c5411a7cf4866aeadc7d108081d8ceba9bc7abe6b14aa21c671ec3/zstandard-0.25.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a3f79487c687b1fc69f19e487cd949bf3aae653d181dfb5fde3bf6d18894706f", size = 640559, upload-time = "2025-09-14T22:16:27.973Z" },
+ { url = "https://files.pythonhosted.org/packages/12/56/354fe655905f290d3b147b33fe946b0f27e791e4b50a5f004c802cb3eb7b/zstandard-0.25.0-cp311-cp311-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:0bbc9a0c65ce0eea3c34a691e3c4b6889f5f3909ba4822ab385fab9057099431", size = 5348020, upload-time = "2025-09-14T22:16:29.523Z" },
+ { url = "https://files.pythonhosted.org/packages/3b/13/2b7ed68bd85e69a2069bcc72141d378f22cae5a0f3b353a2c8f50ef30c1b/zstandard-0.25.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:01582723b3ccd6939ab7b3a78622c573799d5d8737b534b86d0e06ac18dbde4a", size = 5058126, upload-time = "2025-09-14T22:16:31.811Z" },
+ { url = "https://files.pythonhosted.org/packages/c9/dd/fdaf0674f4b10d92cb120ccff58bbb6626bf8368f00ebfd2a41ba4a0dc99/zstandard-0.25.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:5f1ad7bf88535edcf30038f6919abe087f606f62c00a87d7e33e7fc57cb69fcc", size = 5405390, upload-time = "2025-09-14T22:16:33.486Z" },
+ { url = "https://files.pythonhosted.org/packages/0f/67/354d1555575bc2490435f90d67ca4dd65238ff2f119f30f72d5cde09c2ad/zstandard-0.25.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:06acb75eebeedb77b69048031282737717a63e71e4ae3f77cc0c3b9508320df6", size = 5452914, upload-time = "2025-09-14T22:16:35.277Z" },
+ { url = "https://files.pythonhosted.org/packages/bb/1f/e9cfd801a3f9190bf3e759c422bbfd2247db9d7f3d54a56ecde70137791a/zstandard-0.25.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9300d02ea7c6506f00e627e287e0492a5eb0371ec1670ae852fefffa6164b072", size = 5559635, upload-time = "2025-09-14T22:16:37.141Z" },
+ { url = "https://files.pythonhosted.org/packages/21/88/5ba550f797ca953a52d708c8e4f380959e7e3280af029e38fbf47b55916e/zstandard-0.25.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bfd06b1c5584b657a2892a6014c2f4c20e0db0208c159148fa78c65f7e0b0277", size = 5048277, upload-time = "2025-09-14T22:16:38.807Z" },
+ { url = "https://files.pythonhosted.org/packages/46/c0/ca3e533b4fa03112facbe7fbe7779cb1ebec215688e5df576fe5429172e0/zstandard-0.25.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f373da2c1757bb7f1acaf09369cdc1d51d84131e50d5fa9863982fd626466313", size = 5574377, upload-time = "2025-09-14T22:16:40.523Z" },
+ { url = "https://files.pythonhosted.org/packages/12/9b/3fb626390113f272abd0799fd677ea33d5fc3ec185e62e6be534493c4b60/zstandard-0.25.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6c0e5a65158a7946e7a7affa6418878ef97ab66636f13353b8502d7ea03c8097", size = 4961493, upload-time = "2025-09-14T22:16:43.3Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/d3/23094a6b6a4b1343b27ae68249daa17ae0651fcfec9ed4de09d14b940285/zstandard-0.25.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c8e167d5adf59476fa3e37bee730890e389410c354771a62e3c076c86f9f7778", size = 5269018, upload-time = "2025-09-14T22:16:45.292Z" },
+ { url = "https://files.pythonhosted.org/packages/8c/a7/bb5a0c1c0f3f4b5e9d5b55198e39de91e04ba7c205cc46fcb0f95f0383c1/zstandard-0.25.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:98750a309eb2f020da61e727de7d7ba3c57c97cf6213f6f6277bb7fb42a8e065", size = 5443672, upload-time = "2025-09-14T22:16:47.076Z" },
+ { url = "https://files.pythonhosted.org/packages/27/22/503347aa08d073993f25109c36c8d9f029c7d5949198050962cb568dfa5e/zstandard-0.25.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:22a086cff1b6ceca18a8dd6096ec631e430e93a8e70a9ca5efa7561a00f826fa", size = 5822753, upload-time = "2025-09-14T22:16:49.316Z" },
+ { url = "https://files.pythonhosted.org/packages/e2/be/94267dc6ee64f0f8ba2b2ae7c7a2df934a816baaa7291db9e1aa77394c3c/zstandard-0.25.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:72d35d7aa0bba323965da807a462b0966c91608ef3a48ba761678cb20ce5d8b7", size = 5366047, upload-time = "2025-09-14T22:16:51.328Z" },
+ { url = "https://files.pythonhosted.org/packages/7b/a3/732893eab0a3a7aecff8b99052fecf9f605cf0fb5fb6d0290e36beee47a4/zstandard-0.25.0-cp311-cp311-win32.whl", hash = "sha256:f5aeea11ded7320a84dcdd62a3d95b5186834224a9e55b92ccae35d21a8b63d4", size = 436484, upload-time = "2025-09-14T22:16:55.005Z" },
+ { url = "https://files.pythonhosted.org/packages/43/a3/c6155f5c1cce691cb80dfd38627046e50af3ee9ddc5d0b45b9b063bfb8c9/zstandard-0.25.0-cp311-cp311-win_amd64.whl", hash = "sha256:daab68faadb847063d0c56f361a289c4f268706b598afbf9ad113cbe5c38b6b2", size = 506183, upload-time = "2025-09-14T22:16:52.753Z" },
+ { url = "https://files.pythonhosted.org/packages/8c/3e/8945ab86a0820cc0e0cdbf38086a92868a9172020fdab8a03ac19662b0e5/zstandard-0.25.0-cp311-cp311-win_arm64.whl", hash = "sha256:22a06c5df3751bb7dc67406f5374734ccee8ed37fc5981bf1ad7041831fa1137", size = 462533, upload-time = "2025-09-14T22:16:53.878Z" },
+ { url = "https://files.pythonhosted.org/packages/82/fc/f26eb6ef91ae723a03e16eddb198abcfce2bc5a42e224d44cc8b6765e57e/zstandard-0.25.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7b3c3a3ab9daa3eed242d6ecceead93aebbb8f5f84318d82cee643e019c4b73b", size = 795738, upload-time = "2025-09-14T22:16:56.237Z" },
+ { url = "https://files.pythonhosted.org/packages/aa/1c/d920d64b22f8dd028a8b90e2d756e431a5d86194caa78e3819c7bf53b4b3/zstandard-0.25.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:913cbd31a400febff93b564a23e17c3ed2d56c064006f54efec210d586171c00", size = 640436, upload-time = "2025-09-14T22:16:57.774Z" },
+ { url = "https://files.pythonhosted.org/packages/53/6c/288c3f0bd9fcfe9ca41e2c2fbfd17b2097f6af57b62a81161941f09afa76/zstandard-0.25.0-cp312-cp312-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:011d388c76b11a0c165374ce660ce2c8efa8e5d87f34996aa80f9c0816698b64", size = 5343019, upload-time = "2025-09-14T22:16:59.302Z" },
+ { url = "https://files.pythonhosted.org/packages/1e/15/efef5a2f204a64bdb5571e6161d49f7ef0fffdbca953a615efbec045f60f/zstandard-0.25.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6dffecc361d079bb48d7caef5d673c88c8988d3d33fb74ab95b7ee6da42652ea", size = 5063012, upload-time = "2025-09-14T22:17:01.156Z" },
+ { url = "https://files.pythonhosted.org/packages/b7/37/a6ce629ffdb43959e92e87ebdaeebb5ac81c944b6a75c9c47e300f85abdf/zstandard-0.25.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:7149623bba7fdf7e7f24312953bcf73cae103db8cae49f8154dd1eadc8a29ecb", size = 5394148, upload-time = "2025-09-14T22:17:03.091Z" },
+ { url = "https://files.pythonhosted.org/packages/e3/79/2bf870b3abeb5c070fe2d670a5a8d1057a8270f125ef7676d29ea900f496/zstandard-0.25.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:6a573a35693e03cf1d67799fd01b50ff578515a8aeadd4595d2a7fa9f3ec002a", size = 5451652, upload-time = "2025-09-14T22:17:04.979Z" },
+ { url = "https://files.pythonhosted.org/packages/53/60/7be26e610767316c028a2cbedb9a3beabdbe33e2182c373f71a1c0b88f36/zstandard-0.25.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5a56ba0db2d244117ed744dfa8f6f5b366e14148e00de44723413b2f3938a902", size = 5546993, upload-time = "2025-09-14T22:17:06.781Z" },
+ { url = "https://files.pythonhosted.org/packages/85/c7/3483ad9ff0662623f3648479b0380d2de5510abf00990468c286c6b04017/zstandard-0.25.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:10ef2a79ab8e2974e2075fb984e5b9806c64134810fac21576f0668e7ea19f8f", size = 5046806, upload-time = "2025-09-14T22:17:08.415Z" },
+ { url = "https://files.pythonhosted.org/packages/08/b3/206883dd25b8d1591a1caa44b54c2aad84badccf2f1de9e2d60a446f9a25/zstandard-0.25.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aaf21ba8fb76d102b696781bddaa0954b782536446083ae3fdaa6f16b25a1c4b", size = 5576659, upload-time = "2025-09-14T22:17:10.164Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/31/76c0779101453e6c117b0ff22565865c54f48f8bd807df2b00c2c404b8e0/zstandard-0.25.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1869da9571d5e94a85a5e8d57e4e8807b175c9e4a6294e3b66fa4efb074d90f6", size = 4953933, upload-time = "2025-09-14T22:17:11.857Z" },
+ { url = "https://files.pythonhosted.org/packages/18/e1/97680c664a1bf9a247a280a053d98e251424af51f1b196c6d52f117c9720/zstandard-0.25.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:809c5bcb2c67cd0ed81e9229d227d4ca28f82d0f778fc5fea624a9def3963f91", size = 5268008, upload-time = "2025-09-14T22:17:13.627Z" },
+ { url = "https://files.pythonhosted.org/packages/1e/73/316e4010de585ac798e154e88fd81bb16afc5c5cb1a72eeb16dd37e8024a/zstandard-0.25.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f27662e4f7dbf9f9c12391cb37b4c4c3cb90ffbd3b1fb9284dadbbb8935fa708", size = 5433517, upload-time = "2025-09-14T22:17:16.103Z" },
+ { url = "https://files.pythonhosted.org/packages/5b/60/dd0f8cfa8129c5a0ce3ea6b7f70be5b33d2618013a161e1ff26c2b39787c/zstandard-0.25.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:99c0c846e6e61718715a3c9437ccc625de26593fea60189567f0118dc9db7512", size = 5814292, upload-time = "2025-09-14T22:17:17.827Z" },
+ { url = "https://files.pythonhosted.org/packages/fc/5f/75aafd4b9d11b5407b641b8e41a57864097663699f23e9ad4dbb91dc6bfe/zstandard-0.25.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:474d2596a2dbc241a556e965fb76002c1ce655445e4e3bf38e5477d413165ffa", size = 5360237, upload-time = "2025-09-14T22:17:19.954Z" },
+ { url = "https://files.pythonhosted.org/packages/ff/8d/0309daffea4fcac7981021dbf21cdb2e3427a9e76bafbcdbdf5392ff99a4/zstandard-0.25.0-cp312-cp312-win32.whl", hash = "sha256:23ebc8f17a03133b4426bcc04aabd68f8236eb78c3760f12783385171b0fd8bd", size = 436922, upload-time = "2025-09-14T22:17:24.398Z" },
+ { url = "https://files.pythonhosted.org/packages/79/3b/fa54d9015f945330510cb5d0b0501e8253c127cca7ebe8ba46a965df18c5/zstandard-0.25.0-cp312-cp312-win_amd64.whl", hash = "sha256:ffef5a74088f1e09947aecf91011136665152e0b4b359c42be3373897fb39b01", size = 506276, upload-time = "2025-09-14T22:17:21.429Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/6b/8b51697e5319b1f9ac71087b0af9a40d8a6288ff8025c36486e0c12abcc4/zstandard-0.25.0-cp312-cp312-win_arm64.whl", hash = "sha256:181eb40e0b6a29b3cd2849f825e0fa34397f649170673d385f3598ae17cca2e9", size = 462679, upload-time = "2025-09-14T22:17:23.147Z" },
+ { url = "https://files.pythonhosted.org/packages/35/0b/8df9c4ad06af91d39e94fa96cc010a24ac4ef1378d3efab9223cc8593d40/zstandard-0.25.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ec996f12524f88e151c339688c3897194821d7f03081ab35d31d1e12ec975e94", size = 795735, upload-time = "2025-09-14T22:17:26.042Z" },
+ { url = "https://files.pythonhosted.org/packages/3f/06/9ae96a3e5dcfd119377ba33d4c42a7d89da1efabd5cb3e366b156c45ff4d/zstandard-0.25.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a1a4ae2dec3993a32247995bdfe367fc3266da832d82f8438c8570f989753de1", size = 640440, upload-time = "2025-09-14T22:17:27.366Z" },
+ { url = "https://files.pythonhosted.org/packages/d9/14/933d27204c2bd404229c69f445862454dcc101cd69ef8c6068f15aaec12c/zstandard-0.25.0-cp313-cp313-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:e96594a5537722fdfb79951672a2a63aec5ebfb823e7560586f7484819f2a08f", size = 5343070, upload-time = "2025-09-14T22:17:28.896Z" },
+ { url = "https://files.pythonhosted.org/packages/6d/db/ddb11011826ed7db9d0e485d13df79b58586bfdec56e5c84a928a9a78c1c/zstandard-0.25.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bfc4e20784722098822e3eee42b8e576b379ed72cca4a7cb856ae733e62192ea", size = 5063001, upload-time = "2025-09-14T22:17:31.044Z" },
+ { url = "https://files.pythonhosted.org/packages/db/00/87466ea3f99599d02a5238498b87bf84a6348290c19571051839ca943777/zstandard-0.25.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:457ed498fc58cdc12fc48f7950e02740d4f7ae9493dd4ab2168a47c93c31298e", size = 5394120, upload-time = "2025-09-14T22:17:32.711Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/95/fc5531d9c618a679a20ff6c29e2b3ef1d1f4ad66c5e161ae6ff847d102a9/zstandard-0.25.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:fd7a5004eb1980d3cefe26b2685bcb0b17989901a70a1040d1ac86f1d898c551", size = 5451230, upload-time = "2025-09-14T22:17:34.41Z" },
+ { url = "https://files.pythonhosted.org/packages/63/4b/e3678b4e776db00f9f7b2fe58e547e8928ef32727d7a1ff01dea010f3f13/zstandard-0.25.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8e735494da3db08694d26480f1493ad2cf86e99bdd53e8e9771b2752a5c0246a", size = 5547173, upload-time = "2025-09-14T22:17:36.084Z" },
+ { url = "https://files.pythonhosted.org/packages/4e/d5/ba05ed95c6b8ec30bd468dfeab20589f2cf709b5c940483e31d991f2ca58/zstandard-0.25.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3a39c94ad7866160a4a46d772e43311a743c316942037671beb264e395bdd611", size = 5046736, upload-time = "2025-09-14T22:17:37.891Z" },
+ { url = "https://files.pythonhosted.org/packages/50/d5/870aa06b3a76c73eced65c044b92286a3c4e00554005ff51962deef28e28/zstandard-0.25.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:172de1f06947577d3a3005416977cce6168f2261284c02080e7ad0185faeced3", size = 5576368, upload-time = "2025-09-14T22:17:40.206Z" },
+ { url = "https://files.pythonhosted.org/packages/5d/35/398dc2ffc89d304d59bc12f0fdd931b4ce455bddf7038a0a67733a25f550/zstandard-0.25.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3c83b0188c852a47cd13ef3bf9209fb0a77fa5374958b8c53aaa699398c6bd7b", size = 4954022, upload-time = "2025-09-14T22:17:41.879Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/5c/36ba1e5507d56d2213202ec2b05e8541734af5f2ce378c5d1ceaf4d88dc4/zstandard-0.25.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1673b7199bbe763365b81a4f3252b8e80f44c9e323fc42940dc8843bfeaf9851", size = 5267889, upload-time = "2025-09-14T22:17:43.577Z" },
+ { url = "https://files.pythonhosted.org/packages/70/e8/2ec6b6fb7358b2ec0113ae202647ca7c0e9d15b61c005ae5225ad0995df5/zstandard-0.25.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:0be7622c37c183406f3dbf0cba104118eb16a4ea7359eeb5752f0794882fc250", size = 5433952, upload-time = "2025-09-14T22:17:45.271Z" },
+ { url = "https://files.pythonhosted.org/packages/7b/01/b5f4d4dbc59ef193e870495c6f1275f5b2928e01ff5a81fecb22a06e22fb/zstandard-0.25.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:5f5e4c2a23ca271c218ac025bd7d635597048b366d6f31f420aaeb715239fc98", size = 5814054, upload-time = "2025-09-14T22:17:47.08Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/e5/fbd822d5c6f427cf158316d012c5a12f233473c2f9c5fe5ab1ae5d21f3d8/zstandard-0.25.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4f187a0bb61b35119d1926aee039524d1f93aaf38a9916b8c4b78ac8514a0aaf", size = 5360113, upload-time = "2025-09-14T22:17:48.893Z" },
+ { url = "https://files.pythonhosted.org/packages/8e/e0/69a553d2047f9a2c7347caa225bb3a63b6d7704ad74610cb7823baa08ed7/zstandard-0.25.0-cp313-cp313-win32.whl", hash = "sha256:7030defa83eef3e51ff26f0b7bfb229f0204b66fe18e04359ce3474ac33cbc09", size = 436936, upload-time = "2025-09-14T22:17:52.658Z" },
+ { url = "https://files.pythonhosted.org/packages/d9/82/b9c06c870f3bd8767c201f1edbdf9e8dc34be5b0fbc5682c4f80fe948475/zstandard-0.25.0-cp313-cp313-win_amd64.whl", hash = "sha256:1f830a0dac88719af0ae43b8b2d6aef487d437036468ef3c2ea59c51f9d55fd5", size = 506232, upload-time = "2025-09-14T22:17:50.402Z" },
+ { url = "https://files.pythonhosted.org/packages/d4/57/60c3c01243bb81d381c9916e2a6d9e149ab8627c0c7d7abb2d73384b3c0c/zstandard-0.25.0-cp313-cp313-win_arm64.whl", hash = "sha256:85304a43f4d513f5464ceb938aa02c1e78c2943b29f44a750b48b25ac999a049", size = 462671, upload-time = "2025-09-14T22:17:51.533Z" },
+ { url = "https://files.pythonhosted.org/packages/3d/5c/f8923b595b55fe49e30612987ad8bf053aef555c14f05bb659dd5dbe3e8a/zstandard-0.25.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:e29f0cf06974c899b2c188ef7f783607dbef36da4c242eb6c82dcd8b512855e3", size = 795887, upload-time = "2025-09-14T22:17:54.198Z" },
+ { url = "https://files.pythonhosted.org/packages/8d/09/d0a2a14fc3439c5f874042dca72a79c70a532090b7ba0003be73fee37ae2/zstandard-0.25.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:05df5136bc5a011f33cd25bc9f506e7426c0c9b3f9954f056831ce68f3b6689f", size = 640658, upload-time = "2025-09-14T22:17:55.423Z" },
+ { url = "https://files.pythonhosted.org/packages/5d/7c/8b6b71b1ddd517f68ffb55e10834388d4f793c49c6b83effaaa05785b0b4/zstandard-0.25.0-cp314-cp314-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:f604efd28f239cc21b3adb53eb061e2a205dc164be408e553b41ba2ffe0ca15c", size = 5379849, upload-time = "2025-09-14T22:17:57.372Z" },
+ { url = "https://files.pythonhosted.org/packages/a4/86/a48e56320d0a17189ab7a42645387334fba2200e904ee47fc5a26c1fd8ca/zstandard-0.25.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:223415140608d0f0da010499eaa8ccdb9af210a543fac54bce15babbcfc78439", size = 5058095, upload-time = "2025-09-14T22:17:59.498Z" },
+ { url = "https://files.pythonhosted.org/packages/f8/ad/eb659984ee2c0a779f9d06dbfe45e2dc39d99ff40a319895df2d3d9a48e5/zstandard-0.25.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2e54296a283f3ab5a26fc9b8b5d4978ea0532f37b231644f367aa588930aa043", size = 5551751, upload-time = "2025-09-14T22:18:01.618Z" },
+ { url = "https://files.pythonhosted.org/packages/61/b3/b637faea43677eb7bd42ab204dfb7053bd5c4582bfe6b1baefa80ac0c47b/zstandard-0.25.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ca54090275939dc8ec5dea2d2afb400e0f83444b2fc24e07df7fdef677110859", size = 6364818, upload-time = "2025-09-14T22:18:03.769Z" },
+ { url = "https://files.pythonhosted.org/packages/31/dc/cc50210e11e465c975462439a492516a73300ab8caa8f5e0902544fd748b/zstandard-0.25.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e09bb6252b6476d8d56100e8147b803befa9a12cea144bbe629dd508800d1ad0", size = 5560402, upload-time = "2025-09-14T22:18:05.954Z" },
+ { url = "https://files.pythonhosted.org/packages/c9/ae/56523ae9c142f0c08efd5e868a6da613ae76614eca1305259c3bf6a0ed43/zstandard-0.25.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a9ec8c642d1ec73287ae3e726792dd86c96f5681eb8df274a757bf62b750eae7", size = 4955108, upload-time = "2025-09-14T22:18:07.68Z" },
+ { url = "https://files.pythonhosted.org/packages/98/cf/c899f2d6df0840d5e384cf4c4121458c72802e8bda19691f3b16619f51e9/zstandard-0.25.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:a4089a10e598eae6393756b036e0f419e8c1d60f44a831520f9af41c14216cf2", size = 5269248, upload-time = "2025-09-14T22:18:09.753Z" },
+ { url = "https://files.pythonhosted.org/packages/1b/c0/59e912a531d91e1c192d3085fc0f6fb2852753c301a812d856d857ea03c6/zstandard-0.25.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:f67e8f1a324a900e75b5e28ffb152bcac9fbed1cc7b43f99cd90f395c4375344", size = 5430330, upload-time = "2025-09-14T22:18:11.966Z" },
+ { url = "https://files.pythonhosted.org/packages/a0/1d/7e31db1240de2df22a58e2ea9a93fc6e38cc29353e660c0272b6735d6669/zstandard-0.25.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:9654dbc012d8b06fc3d19cc825af3f7bf8ae242226df5f83936cb39f5fdc846c", size = 5811123, upload-time = "2025-09-14T22:18:13.907Z" },
+ { url = "https://files.pythonhosted.org/packages/f6/49/fac46df5ad353d50535e118d6983069df68ca5908d4d65b8c466150a4ff1/zstandard-0.25.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4203ce3b31aec23012d3a4cf4a2ed64d12fea5269c49aed5e4c3611b938e4088", size = 5359591, upload-time = "2025-09-14T22:18:16.465Z" },
+ { url = "https://files.pythonhosted.org/packages/c2/38/f249a2050ad1eea0bb364046153942e34abba95dd5520af199aed86fbb49/zstandard-0.25.0-cp314-cp314-win32.whl", hash = "sha256:da469dc041701583e34de852d8634703550348d5822e66a0c827d39b05365b12", size = 444513, upload-time = "2025-09-14T22:18:20.61Z" },
+ { url = "https://files.pythonhosted.org/packages/3a/43/241f9615bcf8ba8903b3f0432da069e857fc4fd1783bd26183db53c4804b/zstandard-0.25.0-cp314-cp314-win_amd64.whl", hash = "sha256:c19bcdd826e95671065f8692b5a4aa95c52dc7a02a4c5a0cac46deb879a017a2", size = 516118, upload-time = "2025-09-14T22:18:17.849Z" },
+ { url = "https://files.pythonhosted.org/packages/f0/ef/da163ce2450ed4febf6467d77ccb4cd52c4c30ab45624bad26ca0a27260c/zstandard-0.25.0-cp314-cp314-win_arm64.whl", hash = "sha256:d7541afd73985c630bafcd6338d2518ae96060075f9463d7dc14cfb33514383d", size = 476940, upload-time = "2025-09-14T22:18:19.088Z" },
+]
diff --git a/presentations/deep-research/outline.txt b/presentations/deep-research/outline.txt
new file mode 100644
index 0000000..2b8aaf7
--- /dev/null
+++ b/presentations/deep-research/outline.txt
@@ -0,0 +1,767 @@
+================================================================================
+DEEP RESEARCH AGENTS - ARCHITECTURE WALKTHROUGH
+Foo Cafe Malmö | February 5th, 2026 | Emil Wåreus
+================================================================================
+
+--------------------------------------------------------------------------------
+SECTION 1: HOOK (2-3 MINUTES)
+--------------------------------------------------------------------------------
+
+SLIDE: "The Group Project Problem"
+
+SCRIPT:
+"Remember back in school when you had one of those infamous group projects?
+
+At least a few times you probably tried the 'parallel' way of working -
+optimizing for less collaboration and each person owning one segment of the
+report. Each person writing their section in isolation. Background, history,
+theory, whatever you decided on.
+
+Then you meet up 3 hours before the deadline to 'glue the report' together.
+
+How did that turn out?"
+
+[PAUSE for audience reaction]
+
+"The result was probably:
+- Repetitive
+- Inconsistent
+- Different tone of voice per segment
+- Vastly different quality per segment
+- Not the grade you hoped for"
+
+REVEAL:
+"It turns out, when we construct our AI research agents like this -
+plan → parallel research → glue research into report -
+we get the exact same problem!
+
+When no context of the 'evolving report' is shared across sub-agents,
+we get a fragmented ball of mud.
+
+Today I'll show you how we fixed this with something called 'diffusion'."
+
+--------------------------------------------------------------------------------
+SECTION 2: INTRO - EMIL WÅREUS (1-2 MINUTES)
+--------------------------------------------------------------------------------
+
+SLIDE: Speaker introduction
+
+CONTENT:
+- Emil Wåreus
+- General hacker
+- Founder of oaiz [Let humans do human work, AI should do the rest]
+- Passionate about AI research agents and automation
+- ex-co-founder of Debricked [Security + AI startup], exit 2022.
+- Blog: addcommitpush.io
+
+SCRIPT:
+My blog addcommitpush.io is where I write about things like what we're
+discussing today. There's a deep dive on the diffusion architecture there
+if you want to go deeper after this talk."
+
+--------------------------------------------------------------------------------
+SECTION 3: AUDIENCE INTERACTION (3-5 MINUTES)
+--------------------------------------------------------------------------------
+
+SLIDE: "Quick Poll"
+
+QUESTIONS (show of hands):
+
+1. "Who has used ChatGPT or Claude for research tasks?"
+ [Expect most hands]
+
+2. "Who has built or experimented with AI agents?"
+ [Gauge technical level]
+
+3. "Who trusts the AI research reports?"
+ [Open answers]
+
+TRANSITION:
+"Great! So we all know the problem. Let's look at how people have been
+trying to solve it."
+
+--------------------------------------------------------------------------------
+SECTION 4: TIMELINE OF DEEP RESEARCH AGENTS (10-15 MINUTES)
+--------------------------------------------------------------------------------
+
+SLIDE: "The Evolution of Research Agents"
+
+[VISUAL: Horizontal timeline with key systems]
+
+TIMELINE ENTRIES:
+
+JAN 2022 | Chain-of-Thought (Google)
+ | "Show your work" - step-by-step reasoning
+ | Foundation for all agentic AI
+
+OCT 2022 | ReAct (Google Research)
+ | Reasoning + Acting interleaved
+ | First pattern combining thought with tools
+
+JUL 2023 | ToolLLM (Alibaba/Stanford)
+ | Teaching LLMs to use 16,000+ APIs
+ | Enabled specialized tool use at scale
+
+2023 | GPT Researcher (Open Source)
+ | Planner + Executor pattern
+ | First popular open-source research agent
+
+FEB 2024 | STORM (Stanford) ⭐
+ | Multi-perspective conversations
+ | Wikipedia-style article generation
+ | [Will demo this]
+
+FEB 2025 | OpenAI Deep Research
+ | Commercial research agent
+ | Set the industry benchmark
+
+2025 | Perplexity Deep Research
+ | Test-time compute expansion
+ | Real-time search integration
+
+JUL 2025 | Diffusion Deep Research (Google) ⭐
+ | Research as iterative denoising
+ | Self-balancing test-time compute
+ | [Will demo this]
+
+JAN 2026 | OpenClaw crazyness
+
+SCRIPT:
+"Let me walk you through how we got here..."
+
+[Walk through each entry with 30-60 seconds explanation]
+
+KEY INSIGHT:
+"Notice the pattern? We've gone from:
+- Single LLM calls → Chain of thought
+- Static reasoning → Dynamic tool use
+- Single agent → Multi-agent orchestration
+- Linear pipelines → Iterative refinement
+
+The trend is clear: more sophisticated coordination, more iteration,
+more self-correction."
+
+--------------------------------------------------------------------------------
+SECTION 5: CHAIN-OF-THOUGHT & REACT (5 MINUTES)
+--------------------------------------------------------------------------------
+
+SLIDE: "Chain-of-Thought: Show Your Work"
+
+CORE CONCEPT:
+"Before agents could research, they needed to reason. Chain-of-Thought
+(Wei et al., Jan 2022) was the breakthrough that made that possible."
+
+HOW IT WORKS:
+• Standard prompting: Question → Answer (single hop, no reasoning trace)
+• CoT prompting: Question → Step-by-step reasoning → Answer
+
+MECHANISM:
+1. Append "Let's think step by step" (or provide a worked example)
+2. The model generates intermediate reasoning tokens BEFORE the answer
+3. Each reasoning step conditions the next, building a logical chain
+4. The final answer is grounded in the explicit reasoning trace
+
+WHY IT MATTERS:
+• Accuracy jumps dramatically on multi-step problems
+ (GSM8K: 17.9% → 58.1% with CoT on PaLM 540B)
+• The reasoning is inspectable - you can see WHERE it went wrong
+• Foundation for every agent architecture: if a model can't reason
+ through sub-steps, it can't plan or self-correct
+
+EXAMPLE (canonical Roger's tennis balls):
+
+ Standard:
+ Q: "Roger has 5 tennis balls. He buys 2 cans of 3. How many now?"
+ A: "11"
+ (Correct, but no reasoning visible. Fails on harder problems.)
+
+ With CoT:
+ Q: "Roger has 5 tennis balls. He buys 2 cans of 3. How many now?
+ Let's think step by step."
+ A: "1. Roger starts with 5 balls.
+ 2. 2 cans × 3 balls = 6 new balls.
+ 3. 5 + 6 = 11.
+ Answer: 11"
+ (Same answer, but the reasoning chain scales to harder problems.)
+
+SCRIPT:
+"This seems almost trivially simple, but it's the single most important
+idea behind every research agent that followed. If the model can't show
+its work, it can't plan research, evaluate its own findings, or decide
+when to stop. CoT is the foundation."
+
+---
+
+SLIDE: "ReAct: Reasoning + Acting"
+
+CORE CONCEPT:
+"CoT gave models reasoning. ReAct (Yao et al., Oct 2022) gave them
+the ability to ACT on that reasoning - search, fetch, compute - and
+then reason about what they observed. This is the Think-Act-Observe loop."
+
+HOW IT WORKS:
+The model interleaves three phases in a loop:
+
+ THINK → Internal reasoning about what to do next
+ ACT → Call an external tool (search, API, calculator, etc.)
+ OBSERVE → Read the tool's output back into context
+
+The loop repeats until the model decides it has enough information
+to produce a final answer.
+
+MECHANISM:
+1. Model receives a question + access to tools (search, lookup, etc.)
+2. Instead of answering directly, it generates a THOUGHT
+3. Based on the thought, it emits an ACTION (tool call + arguments)
+4. The tool executes and returns an OBSERVATION
+5. The observation is appended to context
+6. Model generates next THOUGHT conditioned on everything so far
+7. Repeat until the model emits a FINISH action with the answer
+
+CONCRETE TRACE:
+
+ THINK "I need to find when WASM 2.0 was released"
+ ACT search("WebAssembly 2.0 release date")
+ OBSERVE "W3C published the recommendation April 2024"
+ THINK "Now I can answer with a verified fact."
+ ACT finish("WebAssembly 2.0 was released April 2024")
+
+WHY IT MATTERS:
+• Grounding: answers backed by real retrieved data, not just training
+• Composability: any tool can be plugged in (search, code exec, APIs)
+• Self-correction: if an observation contradicts a thought, the model
+ can revise its approach in the next iteration
+• THIS is the moment LLMs became agents - reasoning + tool use in a loop
+
+KEY DISTINCTION FROM COT:
+• CoT = pure internal reasoning (no external data)
+• ReAct = reasoning interleaved with external actions
+• CoT can hallucinate confidently. ReAct can verify against reality.
+
+SCRIPT:
+"CoT gave LLMs reasoning. ReAct gave them hands. Every research agent
+you'll see today - STORM, GPT Researcher, Diffusion - is built on this
+Think-Act-Observe loop. The only difference is how they orchestrate it."
+
+DEMO:
+
+Command:
+uv run main.py --agent=react "I am giving a presentation at Foo Café
+in Malmö about deep research AI agents. Research the community and what
+they like, and tell me how to give a good presentation that the audience
+will like. Tailored to this community"
+
+[Show: Think → Search → Observe loop in action, cost tracking]
+
+TRANSITION:
+"Now that we understand the building blocks - reasoning chains and
+tool-augmented loops - let's see how STORM used these to simulate
+expert conversations."
+
+--------------------------------------------------------------------------------
+SECTION 6: STORM ARCHITECTURE (10 MIN + DEMO)
+--------------------------------------------------------------------------------
+
+SLIDE: "STORM: Multi-Perspective Research"
+
+REFERENCE: Stanford OVAL — Shao et al., 2024
+"Assisting in Writing Wikipedia-like Articles From Scratch with LLMs"
+
+CORE CONCEPT:
+"Wikipedia articles are comprehensive because they synthesize MULTIPLE expert
+viewpoints. STORM simulates this by having different expert personas research
+the topic through multi-turn conversations with a search-grounded TopicExpert."
+
+ARCHITECTURE (matches reference implementation):
+ START → discover_perspectives → conduct_interviews (×N parallel via Send)
+ → generate_outline (2-stage) → write_sections (per-section)
+ → write_lead_section → END
+
+---
+
+SLIDE: "STORM: Five Phases" (progressive reveal — 5 steps)
+
+[VISUAL: Vertical flowchart with 5 phase cards connected by down-arrows.
+ Each card shows the inner data flow. Revealed progressively.]
+
+STEP 0 — PHASE 1: DISCOVER PERSPECTIVES (visible immediately)
+
+ Topic → Search related context → Generate 3 expert personas + 1 default
+
+ HOW THIS ACTUALLY WORKS:
+ - Reference: persona_generator.py — FindRelatedTopic + GenPersona
+ - The reference searches for related Wikipedia articles, extracts their
+ TABLE OF CONTENTS (structural skeleton), and uses those outlines as
+ context to generate diverse expert personas
+ - Our implementation: search Tavily for related content, use results as
+ context for persona generation via structured JSON output
+ - A default "Basic fact writer" persona is ALWAYS prepended (reference
+ does this at persona_generator.py:152) — ensures broad factual coverage
+ - Output: 4 named perspectives (1 default + 3 generated), each with a
+ name and description of their expertise and angle
+
+ SCRIPT:
+ "The clever part of STORM starts here. It doesn't hallucinate perspectives —
+ it looks at how humans already structured content on similar topics to figure
+ out which expert viewpoints are needed. Plus, there's always a 'Basic fact
+ writer' — the generalist who covers the fundamentals."
+
+STEP 1 — PHASE 2: CONDUCT INTERVIEWS (parallel via Send())
+
+ [4 lanes side-by-side, each: WikiWriter ↔ TopicExpert (×3 turns)]
+
+ THE CONVERSATION LOOP (reference: knowledge_curation.py — ConvSimulator):
+ - For EACH perspective, STORM spawns a conversation between:
+ • WikiWriter — asks questions from that perspective's viewpoint
+ • TopicExpert — a 2-STEP process:
+ 1. QuestionToQuery: generates 1-3 search queries from the question
+ 2. Search + AnswerQuestion: executes searches, then synthesizes an
+ answer with INLINE CITATIONS [1], [2], [3] referencing sources
+ - They converse for 3 turns (configurable MAX_CONV_TURNS)
+ - Conversation ends when: max turns reached, WikiWriter says
+ "Thank you so much for your help!", or empty utterance
+ - History truncation (reference: knowledge_curation.py:103-110):
+ last 4 turns show full Q&A, earlier turns show question only with
+ "[Omit the answer here due to space limit.]"
+ - All perspective conversations run IN PARALLEL via LangGraph Send()
+ (reference uses ThreadPoolExecutor for the same effect)
+ - After each interview: compiled into a structured summary preserving
+ all facts and inline citations
+ - Output: 4 interview summaries + all [idx]: snippet pairs + all URLs
+
+ SCRIPT:
+ "This is the core innovation. Instead of one agent doing all the research,
+ STORM simulates a panel of experts each having a focused conversation.
+ The TopicExpert doesn't just search — it first generates targeted search
+ queries from the question, executes them, then synthesizes an answer with
+ proper [1], [2] citations. Each conversation builds on prior turns.
+ The conversations run in parallel — they can't see each other."
+
+STEP 2 — PHASE 3: GENERATE OUTLINE (Two-Stage)
+
+ Draft (LLM knowledge only) → Refine (+ conversation data)
+
+ TWO-STAGE OUTLINE GENERATION (reference: outline_generation.py):
+ - Stage 1 — WritePageOutline: LLM generates a draft outline from its OWN
+ parametric knowledge (no conversation data). This ensures structural
+ coherence — the LLM knows what a good article structure looks like.
+ - Stage 2 — WritePageOutlineFromConv: The outline is refined by folding in
+ the actual conversation data. Sections are added, reordered, or merged
+ based on what the experts actually found.
+ - "Introduction", "Conclusion", "References" sections are filtered out
+ - This two-stage approach prevents the outline from being biased by which
+ perspective happened to find the most data.
+
+ SCRIPT:
+ "Notice the outline is built in two stages — first from the LLM's own
+ knowledge of 'what a good article looks like,' then refined with the
+ actual research data. This prevents the structure from being dominated by
+ whichever expert found the most material."
+
+STEP 3 — PHASE 4: WRITE SECTIONS (Per-Section, reference: article_generation.py)
+
+ For each top-level section: section outline + collected info → section text
+
+ PER-SECTION ARTICLE WRITING:
+ - Each top-level section is written INDEPENDENTLY with inline citations
+ [1], [2] referencing the collected snippets from all interviews
+ - Reference uses SentenceTransformer cosine similarity to retrieve the
+ most relevant snippets per section. Our demo passes all collected info
+ (fine for demo-scale queries)
+ - Reference writes sections in parallel (ThreadPoolExecutor). Our demo
+ writes sequentially for clearer logging.
+
+STEP 4 — PHASE 5: LEAD SECTION + ASSEMBLY (reference: article_polish.py)
+
+ Full body → Write lead section → Prepend lead → Build references → Done
+
+ LEAD SECTION + ASSEMBLY:
+ - Lead section is written AFTER the body (so it reflects actual content)
+ - Lead: max 4 paragraphs, standalone overview, sourced with inline cites
+ - References section built from all collected URLs (deduplicated)
+ - Final article: lead + body sections + references
+
+ SCRIPT:
+ "The lead section comes LAST. That might seem backwards, but it makes
+ perfect sense — you can't summarize an article you haven't written yet."
+
+BOTTOM CALLOUT:
+
+ "Linear pipeline — each phase runs exactly once. No backtracking."
+
+ SCRIPT:
+ "And here's the thing to hold in your mind: this entire pipeline runs
+ exactly once. DISCOVER runs once. INTERVIEW runs once. OUTLINE runs once.
+ WRITE runs once. If Phase 2 missed something, there's no way to go back.
+ That's both its strength — it's simple and predictable — and its weakness.
+ We'll come back to this."
+
+---
+
+DEMO:
+"Let me show you this in action..."
+
+Command:
+uv run main.py --agent=storm "I am giving a presentation at Foo Café
+in Malmö about deep research AI agents. Research the community and what
+they like, and tell me how to give a good presentation that the audience
+will like. Tailored to this community"
+
+Expected results: ~75s, ~$0.05, ~48 LLM calls, 60+ sources
+[Show: perspective generation, parallel conversations with citations,
+ two-stage outline, per-section writing, lead section, final output]
+
+--------------------------------------------------------------------------------
+SECTION 7: PLAN-RESEARCH-REPORT PATTERN (5 MINUTES)
+--------------------------------------------------------------------------------
+
+SLIDE: "The Standard Pattern"
+
+SCRIPT:
+"Before we get to diffusion, let me show you the pattern that emerged
+across most implementations. I call it Plan-Research-Report."
+
+THE PATTERN:
+
+1. PLANNING PHASE
+ ├── LLM breaks objective into 3-7 sub-questions
+ └── Assigns questions to specialized agents
+
+2. RESEARCH PHASE
+ ├── Source Finder agent searches web
+ ├── Returns: titles, URLs, summaries, content
+ └── Each sub-question researched in parallel
+
+3. PROCESSING PHASE
+ ├── Summarization agent extracts relevant facts
+ ├── Reviewer scans coverage, flags gaps
+ └── Proposes new questions if needed
+
+4. REPORT PHASE
+ └── Professional writer synthesizes final report
+
+USED BY:
+• OpenAI Deep Research
+• Perplexity Deep Research
+• GPT Researcher
+• Many others
+
+THE PROBLEM:
+"This works... but it's still essentially a linear pipeline.
+If you discover something important late in the process,
+it can't influence earlier decisions.
+
+And the sub-agents researching different topics? They can't
+see each other's work. Sound familiar?"
+
+[Callback to group project problem]
+
+--------------------------------------------------------------------------------
+SECTION 8: DIFFUSION DEEP RESEARCH (15 MIN + DEMO)
+--------------------------------------------------------------------------------
+
+SLIDE: "Research as Diffusion"
+
+THE INSIGHT:
+"What if we treated research like image generation?
+
+In diffusion models for images:
+- Start with random noise
+- Gradually denoise through iterations
+- Use guidance signals to steer the result
+
+For research:
+- Start with a 'noisy' draft (from model knowledge)
+- Gradually refine through research iterations
+- Use retrieved information as guidance"
+
+[VISUAL: Side-by-side comparison table]
+
+Classical Diffusion | Research Diffusion
+-----------------------------|---------------------------
+Random noise (xₜ) | Initial draft from LLM
+Denoising step | Research + draft refinement
+Guidance signal | Retrieved web information
+Clean output (x₀) | Comprehensive research report
+
+HOW IT ACTUALLY WORKS (Reference: Google TTD-DR / thinkdepthai/Deep_Research):
+
+The implementation uses a SUPERVISOR + SUB-AGENT architecture built with
+LangGraph. There are 5 phases:
+
+PHASE 1: RESEARCH BRIEF
+├── User query → LLM → detailed research brief
+├── Maximizes specificity — dimensions to investigate, sources to prioritize
+└── Sets scope and constraints for all subsequent phases
+
+PHASE 2: NOISY DRAFT (the "noise" in diffusion)
+├── Research brief → LLM (higher temperature, ~0.7) → draft report
+├── Generated from LLM's INTERNAL KNOWLEDGE ONLY — no search!
+├── Intentionally speculative — higher temperature encourages coverage
+├── May contain outdated info, gaps, hallucinations
+└── This IS the noise we will "denoise" away
+
+PHASE 3: SUPERVISOR LOOP ⭐ (the "denoising" process)
+├── A SUPERVISOR LLM with TOOL-CALLING orchestrates the research
+│ The supervisor sees the draft + brief and decides what to do next
+│ using TOOLS, not free-form text:
+│
+│ Available tools:
+│ ├── ConductResearch(topic) — spawn a sub-agent for a specific topic
+│ ├── think_tool(reflection) — reflect on progress, plan next steps
+│ └── ResearchComplete() — signal that research is done
+│
+├── When supervisor calls ConductResearch:
+│ ├── A ReAct sub-agent is spawned (LLM + search + think_tool loop)
+│ ├── Sub-agent runs Think → Search → Observe → Think → ... loop
+│ ├── Uses Tavily web search for real-time information
+│ ├── After sub-agent finishes, findings are COMPRESSED
+│ │ (raw conversation → clean summary preserving ALL facts + URLs)
+│ └── Compressed research is returned to supervisor as a tool result
+│
+├── After research completes, draft is REFINED with new findings
+│ (this is the actual "denoising" step — replacing speculation with evidence)
+│
+├── Supervisor loops: think → research → refine → think → research → ...
+│ Until it calls ResearchComplete or hits max iterations (8)
+│
+└── Up to 3 sub-agents can be dispatched per iteration (parallel research)
+
+PHASE 4: FINAL REPORT GENERATION
+├── All research is done — draft has been refined with real evidence
+├── Final polish pass: proper headings, inline [Source: URL] citations
+├── Comprehensive Sources section listing all URLs
+└── The refined draft + findings + brief → final professional report
+
+PHASE 5: OUTPUT
+└── Return the final report with cost and timing metadata
+
+WHY THIS ARCHITECTURE WORKS:
+
+1. TOOL-CALLING SUPERVISOR:
+ The supervisor doesn't generate free-form plans. It calls structured tools.
+ ConductResearch, think_tool, ResearchComplete. This prevents the supervisor
+ from hallucinating a plan — it must take concrete actions.
+
+2. REACT SUB-AGENTS:
+ Each sub-agent is a full ReAct loop (Think-Act-Observe). It reasons about
+ what to search, executes the search, reads results, and iterates. This is
+ the same pattern from Section 5 — nested inside the diffusion loop.
+
+3. COMPRESSION BEFORE RETURN:
+ Raw sub-agent conversations contain tool calls, search results, reflections.
+ Passing all of this to the supervisor would create context overload.
+ Instead, findings are compressed into a clean summary preserving ALL facts
+ and source URLs. This is critical for keeping the supervisor's context clean.
+
+4. DRAFT REFINEMENT AS DENOISING:
+ After each batch of research, the draft is refined with the new findings.
+ Claims contradicted by research are corrected. Gaps are filled. Sources
+ are cited. Each refinement step replaces speculation with verified facts.
+ This IS the denoising — each iteration reduces uncertainty in the draft.
+
+5. EVIDENCE-BASED COMPLETION:
+ The supervisor calls ResearchComplete only when it judges the findings
+ are comprehensive. The criteria is about evidence quality, not draft
+ appearance. A polished-looking draft can still hide missing information.
+
+THE CRITICAL INSIGHT:
+"Notice: the supervisor checks if FINDINGS are comprehensive,
+NOT if the draft looks good.
+
+This is crucial. If you stop when the draft looks polished,
+you might stop before you've actually found all the information.
+The completion criteria is about EVIDENCE, not AESTHETICS."
+
+[VISUAL: Draft evolution animation - use DraftDenoising component]
+
+PARALLEL SUB-AGENTS:
+
+[VISUAL: ParallelAgents component]
+
+"When the supervisor calls ConductResearch multiple times in one turn,
+it spawns up to 3 sub-agents in parallel.
+
+Each sub-agent:
+- Has isolated context (can't see others' work)
+- Runs its own ReAct loop (LLM + search + think_tool)
+- Findings are compressed before returning to supervisor
+
+The isolation is intentional - prevents topic A from
+biasing topic B's research. The compression ensures the
+supervisor's context stays manageable."
+
+THE TWO GAPS:
+
+[VISUAL: TwoStageGap component]
+
+INFORMATION GAP (Phase 3 - Supervisor Loop)
+├── Focus: WHAT information exists
+├── Draft updates are functional, not polished
+├── Prioritizes breadth of coverage
+└── Based on findings completeness, not appearance
+
+GENERATION GAP (Phase 4 - Final Report)
+├── Focus: HOW to present information
+├── All information already gathered
+├── Polish for readability, citations, structure
+└── Professional formatting and source listing
+
+"There's a trade-off between these gaps. You can't optimize
+for pretty writing while you're still hunting for facts.
+Otherwise you're polishing hallucinations."
+
+DEMO:
+
+Command:
+uv run main.py --agent=diffusion "I am giving a presentation at Foo Café
+in Malmö about deep research AI agents. Research the community and what
+they like, and tell me how to give a good presentation that the audience
+will like. Tailored to this community"
+
+[Show:
+- Phase 1: Brief generation (query → structured research plan)
+- Phase 2: Noisy draft from LLM knowledge only
+- Supervisor loop iterations:
+ - think_tool reflections
+ - ConductResearch calls spawning sub-agents
+ - Sub-agents searching and compressing
+ - Draft refinement after each research batch
+- Final report generation
+- Cost + timing summary]
+
+--------------------------------------------------------------------------------
+SECTION 9: WHAT DRIVES PERFORMANCE (10 MINUTES)
+--------------------------------------------------------------------------------
+
+SLIDE: "Benchmark Performance"
+
+DEEPRESEARCH BENCH:
+• 100 PhD-level research tasks
+• Designed by domain experts
+• Two evaluation frameworks
+
+RACE FRAMEWORK (Report Quality):
+├── Comprehensiveness - coverage breadth and depth
+├── Insight/Depth - quality, originality of analysis
+├── Instruction Following - adherence to requirements
+└── Readability - clarity, structure, fluency
+
+FACT FRAMEWORK (Citation Quality):
+├── Citation Accuracy - % correctly supported
+└── Effective Citations - average verified per task
+
+RESULTS:
+Google TTD-DR (Diffusion) vs OpenAI Deep Research:
+• 74.5% win rate
+• +7.7% on one dataset
+• +1.7% on another
+
+WHY DIFFUSION WINS:
+
+[Table format]
+
+Factor | Impact
+----------------------------|---------------------------
+Iterative refinement | Catches gaps → Comprehensiveness
+Parallel execution | Diverse perspectives → Coverage
+Explicit completion criteria| Evidence-based → Validated
+Self-balancing adaptivity | Right-sized research
+Draft as context anchor | Persistent context → Readability
+Quality rules in final gen | Systematic → Insight
+
+CONTEXT ENGINEERING:
+
+[Table format]
+
+Problem | Description | Solution
+---------------------|--------------------------------|------------------
+Context Poisoning | Hallucinations enter context | Draft as verified state
+Context Distraction | Too much context | Parallel isolated agents
+Context Confusion | Superfluous context influences | Structured compression
+Context Clash | Parts of context disagree | Supervisor resolution
+
+--------------------------------------------------------------------------------
+SECTION 10: PRACTICAL TAKEAWAYS (5 MINUTES)
+--------------------------------------------------------------------------------
+
+SLIDE: "What You Can Apply Today"
+
+1. START WITH A DRAFT
+ Even a rough draft from internal knowledge reveals gaps faster
+ than starting from scratch.
+
+2. DEDUPLICATE BY URL BEFORE SYNTHESIS
+ Same source cited with different wording = noise.
+ Deduplicate to keep signal high.
+
+3. COMPLETION = EVIDENCE, NOT AESTHETICS
+ Run diverse queries. Only stop when they yield no new facts.
+ Pretty writing can hide missing information.
+
+4. CAP ITERATIONS AND CONCURRENCY
+ 8 supervisor loops max, 3 concurrent sub-agents max.
+ Prevents thrash, keeps costs predictable (~$0.06 per run).
+
+5. SEPARATE INFORMATION FROM GENERATION
+ Don't polish until facts are locked.
+ Otherwise you're polishing hallucinations.
+
+6. ISOLATE SUB-AGENT CONTEXTS
+ Each sub-researcher needs complete, standalone instructions.
+ They can't see other agents' work - and that's a feature.
+
+7. COMPRESS FINDINGS, PRESERVE EVERYTHING
+ When returning to supervisor, remove duplicates only.
+ Never summarize or paraphrase research findings.
+
+--------------------------------------------------------------------------------
+SECTION 11: Q&A AND DISCUSSION (10-15 MINUTES)
+--------------------------------------------------------------------------------
+
+SLIDE: "Questions?"
+
+PREPARED QUESTIONS TO PROMPT DISCUSSION:
+
+• "What research tasks would you want to automate?"
+• "Anyone have experience with the commercial products?"
+• "What concerns do you have about automated research?"
+
+RESOURCES:
+
+Blog Post (deeper dive):
+https://addcommitpush.io/blog/diffusion-deep-research
+
+Reference Implementation (Diffusion Deep Research):
+https://github.com/thinkdepthai/Deep_Research
+
+STORM (Stanford):
+https://github.com/stanford-oval/storm
+
+DeepResearch Bench:
+https://huggingface.co/spaces/muset-ai/DeepResearch-Bench-Leaderboard
+
+CLOSING:
+"Thanks for listening! The code is open source if you want to try it.
+And there's pizza - let's chat!"
+
+================================================================================
+END OF PRESENTATION
+================================================================================
+
+TOTAL TIME: ~75-85 minutes (adjustable based on Q&A)
+
+DEMO PREPARATION CHECKLIST:
+□ Python demos tested (uv run main.py --agent=react/storm/diffusion)
+□ API keys funded (OpenRouter for LLMs, Tavily for search)
+□ .env file in demos/ directory with OPENROUTER_API_KEY + TAVILY_API_KEY
+□ Pre-run queries to warm up cache and verify costs
+□ Backup screenshots/recordings if demos fail
+□ Test projector/screen resolution (presentation at localhost:3001)
+
+EQUIPMENT NEEDED:
+□ Laptop with demos ready
+□ USB backup
+□ Presentation slides (localhost:3001/presentations/deep-research)
+□ Terminal ready in presentations/deep-research/demos/ directory
+□ Water for speaking
diff --git a/presentations/deep-research/pitch.md b/presentations/deep-research/pitch.md
new file mode 100644
index 0000000..b1f337b
--- /dev/null
+++ b/presentations/deep-research/pitch.md
@@ -0,0 +1,9 @@
+# Let's build all versions of historical Deep Research agents
+
+Deep research agents, like OpenAI, Gemini, or Claude's deep researchers, are extremely powerful to gather information, surf the web, and compile reports.
+It has become a daily habit of mine to spin up multiple deep researchers to help gather knowledge and insights, but how do they work under the hood?
+In this talk, we will go through how DR agents evolved, from chain-of-thoughts, STORM, and finally explore the more modern approaches to let AI explore A LOT of information accurately. We will even try to build some of them together!
+
+
+# Emil Wåreus
+is a spaghetti coder, ML trainer, agent builder, and cat owner. He previously founded Debricked, a security based startup based in Malmö that he exited by acquisition a few years back. He is now building his next ventures, including oaiz.io for AI that builds AI, podidex.com that creates personal podcasts, and valkompass.ai to help voters explore swedish politics.
\ No newline at end of file
diff --git a/presentations/deep-research/plan.md b/presentations/deep-research/plan.md
new file mode 100644
index 0000000..0e01c23
--- /dev/null
+++ b/presentations/deep-research/plan.md
@@ -0,0 +1,300 @@
+# Deep Research Agents - Architecture Walkthrough
+## Presentation Plan for Foo Cafe Malmö - February 5th, 2026
+
+---
+
+## Project Status
+
+### Completed
+- [x] Research Foo Cafe Malmö - audience, style, vibe
+- [x] Research deep research agent history and timeline
+- [x] Analyze codebase (STORM, Deep_Research Python implementation)
+- [x] Read Diffusion Deep Research blog post content
+- [x] Create folder structure
+- [x] Create research folder with all references
+- [x] Create comprehensive presentation outline (outline.txt)
+- [x] Create research files (timeline.md, storm.md, diffusion.md, benchmarks.md, foo-cafe.md, references.md)
+- [x] Create slides.md with 33 slides, speaker notes, and timing estimates
+
+### Ready for Use
+All materials are complete and ready for presentation development!
+
+### Files Created
+- `plan.md` - Master plan and status tracking
+- `outline.txt` - Full presentation script/outline
+- `slides.md` - **33 slides with speaker notes and timing (~73 min)**
+- `research/timeline.md` - Complete history of deep research agents
+- `research/storm.md` - STORM architecture deep dive
+- `research/diffusion.md` - Diffusion architecture deep dive
+- `research/benchmarks.md` - Performance metrics and evaluation
+- `research/foo-cafe.md` - Venue research
+- `research/references.md` - Complete bibliography
+
+---
+
+## Venue Context: Foo Cafe Malmö
+
+### Audience Profile
+- Software developers and engineers (strong Node.js community)
+- Tech entrepreneurs and startup founders
+- Data scientists and AI/ML professionals
+- Inclusive community - "everybody is invited"
+
+### Presentation Style That Works
+- Casual yet professional approach
+- Technical talks with practical demos
+- Interactive Q&A sessions
+- Knowledge sharing focus with growth orientation
+- Previous Emil talks: "The State of AI", "Inside Debricked: Lessons from a Startup's Tech Journey"
+
+### Venue Vibe
+- Community-driven, foundation-based
+- Complementary pizza and drinks
+- Relaxed networking atmosphere
+- Daily programming with events year-round
+
+---
+
+## Presentation Structure
+
+### 1. HOOK (2-3 minutes)
+**The Group Project Problem**
+- Remember school group projects where everyone wrote their section in isolation?
+- The result: repetitive, inconsistent, different tones, varying quality
+- REVEAL: This is exactly how most AI research agents work today!
+- Tease: "Today I'll show you how we fixed this with diffusion"
+
+### 2. INTRO - Emil Wåreus (1-2 minutes)
+- Co-founder and Head of Data Science at Debricked
+- Passionate about AI research agents and automation
+- Previous talks at Foo Cafe: "The State of AI", semantic code search
+- Blog: addcommitpush.io
+
+### 3. AUDIENCE INTERACTION (3-5 minutes)
+**Questions to ask:**
+1. "Who has used ChatGPT or Claude for research tasks?" (hands up)
+2. "Who has noticed AI giving inconsistent or repetitive information in long outputs?" (hands up)
+3. "Who has built or experimented with AI agents?" (hands up)
+4. "What's the longest research task you've trusted to an AI?" (open answers)
+
+**Why this works:** Creates engagement, gauges audience level, sets up the problem
+
+### 4. TIMELINE OF DEEP RESEARCH AGENTS (10-15 minutes)
+
+#### Visual Timeline (key milestones):
+
+| Date | System | Organization | Key Innovation |
+|------|--------|--------------|----------------|
+| Jan 2022 | Chain-of-Thought | Google | Step-by-step reasoning |
+| Oct 2022 | ReAct | Google Research | Reasoning + Acting interleaved |
+| Jul 2023 | ToolLLM | Alibaba/Stanford | 16,000+ API mastery |
+| 2023 | GPT Researcher | Open Source | Planner + Executor pattern |
+| Feb 2024 | **STORM** | Stanford | Multi-perspective conversations |
+| Feb 2025 | OpenAI Deep Research | OpenAI | Commercial research agent |
+| 2025 | Perplexity Deep Research | Perplexity AI | Test-time compute expansion |
+| Jul 2025 | **Diffusion Deep Research** | Google DeepMind | Diffusion-based iterative refinement |
+| 2025 | Skywork DeepResearchAgent | Skywork AI | Hierarchical multi-agent |
+
+### 5. ARCHITECTURE WALKTHROUGHS (30-40 minutes)
+
+#### 5.1 STORM Architecture (10 min + demo)
+**Core Concept:** Multi-perspective conversation simulation
+
+**Phases:**
+1. DISCOVER - Survey topics, generate 3-6 expert perspectives
+2. CONVERSE - Parallel WikiWriter↔TopicExpert dialogues
+3. ANALYZE - Extract facts, detect contradictions, fill gaps
+4. SYNTHESIZE - Two-phase outline → final report
+
+**Key Innovation:** Perspective-based research ensures diverse viewpoints
+
+**DEMO:** Run `/storm` query in go-research REPL
+
+#### 5.2 Plan-Research-Report Pattern (5 min)
+**Core Concept:** Standard emerging pattern across implementations
+
+**Flow:**
+1. Planning Phase - Break objective into sub-questions
+2. Research Phase - Source Finder with web search
+3. Processing Phase - Summarization + gap detection
+4. Report Phase - Professional synthesis
+
+**Used by:** OpenAI DR, Perplexity DR, GPT Researcher
+
+#### 5.3 Diffusion Deep Research (15 min + demo)
+**Core Concept:** Research as iterative denoising
+
+**The Insight:**
+- Initial draft from LLM knowledge = "noisy" state
+- Each research iteration = "denoising step"
+- Retrieved information = "guidance signal"
+- Final report = "clean output"
+
+**Four Phases:**
+1. Brief Generation - Transform query to research brief
+2. Initial Draft - Generate from internal knowledge only (the "noise")
+3. Diffusion Loop (Supervisor Subgraph):
+ - Generate research questions for gaps
+ - Conduct parallel research
+ - Refine draft (denoise)
+ - Assess completeness
+4. Final Report - Apply quality rules
+
+**Key Innovations:**
+- Self-balancing test-time compute
+- Parallel sub-agents with isolated contexts
+- Completion based on findings, not draft appearance
+- Draft as persistent context anchor
+
+**DEMO:** Run `/think_deep` query in go-research REPL
+
+### 6. WHAT DRIVES PERFORMANCE (10 minutes)
+
+#### Benchmark: DeepResearch Bench
+- 100 PhD-level research tasks
+- RACE Framework (Report Quality): Comprehensiveness, Insight, Instruction Following, Readability
+- FACT Framework (Citation Quality): Accuracy, Effective Citations
+
+#### Why Diffusion Wins:
+1. Iterative refinement catches gaps → Higher Comprehensiveness
+2. Parallel execution → Better Coverage
+3. Explicit completion criteria → Validated Comprehensiveness
+4. Self-balancing adaptivity → Right-Sized Research
+5. Draft as context anchor → Higher Readability
+6. Quality rules in final generation → Higher Insight
+
+#### Context Engineering Considerations:
+| Problem | Description | Diffusion Solution |
+|---------|-------------|-------------------|
+| Context Poisoning | Hallucinations enter context | Draft as verified state |
+| Context Distraction | Too much context | Parallel isolated agents |
+| Context Confusion | Superfluous context | Structured compression |
+| Context Clash | Disagreeing context | Supervisor resolution |
+
+### 7. PRACTICAL TAKEAWAYS (5 minutes)
+1. Start with a draft - reveals gaps faster
+2. Deduplicate by URL before synthesis
+3. Completion is about evidence coverage, not aesthetics
+4. Cap iterations and concurrency (15 loops, 3 agents)
+5. Separate information gap from generation gap
+6. Isolate sub-agent contexts
+7. Compress findings, preserve everything
+
+### 8. Q&A and DISCUSSION (10-15 minutes)
+
+---
+
+## Demo Preparation
+
+### Required Setup:
+```bash
+cd go-research
+cp .env.example .env
+# Add API keys: OPENROUTER_API_KEY, BRAVE_API_KEY
+go build -o research ./cmd/research
+./research
+```
+
+### Demo Queries (prepare 2-3):
+1. `/storm "What are the security implications of WebAssembly for sandboxed execution?"`
+2. `/think_deep "Compare the architectural patterns of STORM vs Diffusion research agents"`
+3. `/fast "What is the ReAct agent pattern?"`
+
+### Backup Plan:
+- Pre-recorded demos if API issues
+- Screenshots of key visualizations
+- Code walkthrough of key functions
+
+---
+
+## Visual Assets Needed
+
+### Infographics (from blog post):
+1. DiffusionOverview - Self-balancing test-time diffusion
+2. DraftDenoising - How draft evolves through iterations
+3. ParallelAgents - Parallel fan-out visualization
+4. TwoStageGap - Information vs Generation gap
+5. RACEMetrics - Benchmark performance
+6. DiffusionLoopStep - Single iteration visualization
+
+### Timeline Graphic:
+- Create horizontal timeline with key systems
+- Color-code by organization
+- Show key innovations as annotations
+
+### Architecture Diagrams:
+1. STORM 4-phase flow
+2. Diffusion supervisor/sub-agent pattern
+3. Plan-Research-Report pattern
+
+---
+
+## Research References to Include
+
+### Papers:
+1. STORM (arXiv:2402.14207) - Stanford, Feb 2024
+2. Chain-of-Thought (arXiv:2201.11903) - Google, Jan 2022
+3. ReAct (arXiv:2210.03629) - Google, Oct 2022
+4. Deep Researcher TTD-DR (arXiv:2507.16075) - Google, Jul 2025
+5. Deep Research Survey (arXiv:2508.12752) - Aug 2025
+6. Deep Research Agents Roadmap (arXiv:2506.18096) - Jun 2025
+
+### Key Resources:
+- STORM GitHub: github.com/stanford-oval/storm
+- GPT Researcher Docs: docs.gptr.dev
+- DeepResearch Bench: huggingface.co/spaces/muset-ai/DeepResearch-Bench-Leaderboard
+- ThinkDepth.ai Reference Implementation: github.com/thinkdepthai/Deep_Research
+- My Go Implementation: github.com/emilwareus/addcommitpush.io/tree/main/go-research
+
+### Blog Posts:
+- Google Research: Deep Researcher with Test-Time Diffusion
+- Paichun Lin: Self-Balancing Agentic AI
+- My blog: addcommitpush.io/blog/diffusion-deep-research
+
+---
+
+## Timing Breakdown (60 minutes total)
+
+| Section | Duration | Cumulative |
+|---------|----------|------------|
+| Hook | 2-3 min | 3 min |
+| Intro | 1-2 min | 5 min |
+| Audience Interaction | 3-5 min | 10 min |
+| Timeline | 10-15 min | 25 min |
+| STORM Walkthrough + Demo | 10 min | 35 min |
+| Plan-Research-Report | 5 min | 40 min |
+| Diffusion Walkthrough + Demo | 15 min | 55 min |
+| Performance Drivers | 10 min | 65 min |
+| Practical Takeaways | 5 min | 70 min |
+| Q&A | 10-15 min | 85 min |
+
+**Total: ~75-85 minutes** (adjust based on Foo Cafe slot)
+
+---
+
+## Notes for Presentation Day
+
+1. Arrive early to test projector/screen
+2. Have demos pre-loaded and tested
+3. Bring backup on USB drive
+4. Check API keys are funded
+5. Have offline fallback ready
+6. Prepare water for speaking
+7. Engage with audience during networking after
+
+---
+
+## File Structure
+
+```
+presentations/deep-research/
+├── plan.md # This file
+├── outline.txt # Detailed presentation outline
+└── research/
+ ├── timeline.md # Full timeline with all systems
+ ├── storm.md # STORM architecture notes
+ ├── diffusion.md # Diffusion architecture notes
+ ├── benchmarks.md # Performance benchmarks
+ ├── foo-cafe.md # Venue research
+ └── references.md # All paper/URL references
+```
diff --git a/presentations/deep-research/research/benchmarks.md b/presentations/deep-research/research/benchmarks.md
new file mode 100644
index 0000000..a0d63bc
--- /dev/null
+++ b/presentations/deep-research/research/benchmarks.md
@@ -0,0 +1,239 @@
+# Deep Research Benchmarks
+
+## Performance Metrics and Evaluation Frameworks
+
+---
+
+## DeepResearch Bench
+
+The comprehensive benchmark for evaluating Deep Research Agents.
+
+**Leaderboard:** https://huggingface.co/spaces/muset-ai/DeepResearch-Bench-Leaderboard
+**Documentation:** https://deepresearch-bench.github.io/
+
+### Dataset Composition
+
+- **100 PhD-level research tasks**
+- Designed by domain experts
+- Covers multiple domains:
+ - Science & Technology
+ - Finance & Business
+ - Software Engineering
+ - Other specialized fields
+
+### Evaluation Dimensions
+
+Two primary frameworks:
+1. **RACE** - Report quality evaluation
+2. **FACT** - Citation quality evaluation
+
+---
+
+## RACE Framework (Report Quality)
+
+RACE evaluates the quality of generated research reports through four dimensions:
+
+### 1. Comprehensiveness
+
+**Definition:** Coverage breadth and depth of the research topic
+
+**Measures:**
+- Did the report address all aspects of the research question?
+- Are there significant gaps in coverage?
+- Is the depth of analysis appropriate?
+
+**Connection to Diffusion:** Measures "information gap" closing
+
+### 2. Insight / Depth
+
+**Definition:** Quality, originality, logic, and value of analysis
+
+**Criteria:**
+- Does the report provide novel insights?
+- Is the reasoning logical and well-structured?
+- Does it go beyond surface-level information?
+
+**Connection to Diffusion:** Insightfulness rules (granular breakdown, mapping tables, nuanced discussion)
+
+### 3. Instruction Following
+
+**Definition:** Adherence to task requirements and constraints
+
+**Measures:**
+- Did the report follow the specific instructions given?
+- Are formatting requirements met?
+- Are scope constraints respected?
+
+### 4. Readability
+
+**Definition:** Clarity of structure, fluency, and ease of understanding
+
+**Measures:**
+- Is the report well-organized?
+- Is the language clear and professional?
+- Is it easy to navigate and understand?
+
+**Connection to Diffusion:** Measures "generation gap" closing
+
+---
+
+## FACT Framework (Citation Quality)
+
+FACT evaluates information retrieval and grounding capabilities:
+
+### Evaluation Process
+
+1. **Extract** statement-URL pairs from the report
+2. **Deduplicate** redundant pairs
+3. **Verify** via web scrape + LLM judgment
+4. **Calculate** metrics
+
+### Metrics
+
+#### Citation Accuracy
+- **Definition:** Percentage of citations correctly supported by their sources
+- **Formula:** (Verified Citations / Total Citations) × 100
+
+#### Effective Citations
+- **Definition:** Average number of verified citations per task
+- **Importance:** Measures both quantity and quality of sourcing
+
+---
+
+## Comparative Performance
+
+### Google TTD-DR (Diffusion) vs Others
+
+**Performance against OpenAI Deep Research:**
+- **Win Rate:** 74.5%
+- **Dataset 1:** +7.7% improvement
+- **Dataset 2:** +1.7% improvement
+
+### Why Diffusion Outperforms
+
+| Factor | Explanation | Metric Impact |
+|--------|-------------|---------------|
+| Iterative refinement | Catches gaps through multiple passes | Higher Comprehensiveness |
+| Parallel execution | Diverse perspectives gathered efficiently | Better Coverage |
+| Explicit completion criteria | Based on findings, not appearance | Validated Comprehensiveness |
+| Self-balancing | Adapts iterations to complexity | Right-sized research |
+| Draft as context anchor | Persistent verified context | Higher Readability |
+| Quality rules in final generation | Systematic application | Higher Insight |
+
+---
+
+## System Performance Characteristics
+
+### Typical Metrics
+
+| System | Report Time | Cost | Special Features |
+|--------|-------------|------|------------------|
+| GPT Researcher | ~3 min | ~$0.005 | 5-6 page reports |
+| Perplexity DR | 2-4 min | Pro subscription | TTC architecture |
+| OpenAI DR | 5-10 min | Pro/Plus subscription | Commercial grade |
+| Diffusion (Go impl) | 5-15 min | ~$0.05-0.10 | Configurable iterations |
+
+### Iteration Scaling
+
+| Complexity | Typical Iterations | Sub-agents | Time |
+|------------|-------------------|------------|------|
+| Simple | 2-3 | 1-2 | 2-5 min |
+| Moderate | 5-8 | 2-3 | 5-10 min |
+| Complex | 10-15 | 3 | 10-15 min |
+
+---
+
+## Skywork DeepResearchAgent Benchmarks
+
+### Overall Performance
+
+| Metric | Score |
+|--------|-------|
+| Average Test Performance | 83.39 |
+| Level 1 | 93.55 |
+| Level 2 | 83.02 |
+| Level 3 | 65.31 |
+
+### Benchmark Comparison
+
+Outperforms on:
+- **SimpleQA** - Simple question answering
+- **GAIA** - General AI Assistants
+- **HLE** - High-Level Evaluation
+
+---
+
+## STORM Benchmarks (NAACL 2024)
+
+### From Original Paper
+
+**vs Outline-Driven Baselines:**
+- **Organization:** +25% improvement
+- **Coverage:** +10% improvement
+
+**FActScore:** Comparable to human-written Wikipedia articles
+
+### Strengths Measured
+
+- Multi-perspective ensures diverse viewpoint coverage
+- Conversation simulation generates high-quality questions
+- Two-phase outline prevents incoherent structure
+
+---
+
+## Benchmark Considerations
+
+### What Benchmarks Measure Well
+
+- Report coherence and structure
+- Citation accuracy and grounding
+- Coverage of key topics
+- Following explicit instructions
+
+### What Benchmarks Miss
+
+- Real-world user satisfaction
+- Time-to-insight for practical use cases
+- Handling of ambiguous or evolving queries
+- Integration with existing workflows
+
+### Evaluation Pitfalls
+
+1. **Over-optimization:** Systems may optimize for benchmark patterns
+2. **Domain bias:** Performance varies significantly by domain
+3. **Static evaluation:** Real queries are often iterative
+4. **Citation gaming:** More citations ≠ better research
+
+---
+
+## Practical Performance Testing
+
+For the presentation demo, prepare these test scenarios:
+
+### Simple Query (2-3 iterations expected)
+```
+What is the ReAct agent pattern?
+```
+Expected: Quick answer, 1-2 sources, ~2 min
+
+### Moderate Query (5-8 iterations expected)
+```
+Compare STORM and Diffusion research architectures
+```
+Expected: Structured comparison, 5-10 sources, ~5 min
+
+### Complex Query (10+ iterations expected)
+```
+What are the security implications of WebAssembly for sandboxed execution in cloud environments?
+```
+Expected: Deep analysis, 10+ sources, ~10 min
+
+---
+
+## Sources
+
+- DeepResearch Bench: https://deepresearch-bench.github.io/
+- Leaderboard: https://huggingface.co/spaces/muset-ai/DeepResearch-Bench-Leaderboard
+- STORM Paper: https://arxiv.org/abs/2402.14207
+- Google TTD-DR Paper: https://arxiv.org/html/2507.16075v1
+- Deep Research Survey: https://arxiv.org/abs/2508.12752
diff --git a/presentations/deep-research/research/diffusion.md b/presentations/deep-research/research/diffusion.md
new file mode 100644
index 0000000..3c57843
--- /dev/null
+++ b/presentations/deep-research/research/diffusion.md
@@ -0,0 +1,353 @@
+# Diffusion Deep Research Architecture
+
+## Self-Balancing Test-Time Diffusion for Research Agents
+
+---
+
+## Overview
+
+Diffusion Deep Research treats research report generation as an iterative refinement process, analogous to how diffusion models generate images. Instead of a linear pipeline, the system starts with a "noisy" draft and progressively "denoises" it through research iterations.
+
+**Origin:** Google DeepMind (July 2025)
+**Paper:** arXiv:2507.16075
+**Blog:** https://research.google/blog/deep-researcher-with-test-time-diffusion/
+
+---
+
+## The Core Insight
+
+### Traditional Pipeline Problem
+
+```
+Query → Search → Synthesize → Report
+```
+
+**Limitations:**
+1. **Information Loss:** Late discoveries can't influence early decisions
+2. **No Self-Correction:** Errors propagate to final output
+3. **Static Search Strategy:** Can't adapt based on findings
+4. **Coherence Degradation:** Long reports lose consistency
+
+### Diffusion Solution
+
+```
+Query → Brief → Draft → [Research → Refine] × N → Report
+```
+
+The iterative nature mirrors how humans actually conduct research—cycles of searching, reasoning, and revision.
+
+---
+
+## Diffusion Analogy
+
+### Classical Diffusion Models (Images)
+
+**Forward Diffusion:** Add noise to data
+```
+x₀ → x₁ → x₂ → ... → xₜ (pure noise)
+```
+
+**Reverse Diffusion:** Learn to denoise
+```
+xₜ → xₜ₋₁ → ... → x₁ → x₀ (clean data)
+```
+
+### Research Diffusion
+
+| Classical Diffusion | Research Diffusion |
+|--------------------|--------------------|
+| Random noise (xₜ) | Initial draft from model knowledge |
+| Denoising step | Research iteration + draft refinement |
+| Guidance signal | Retrieved information from web search |
+| Clean output (x₀) | Comprehensive, accurate research report |
+
+**Key Insight:** The initial draft generated purely from LLM training data represents the "noisy" starting state. Each iteration of identifying gaps, searching, and incorporating findings acts as a denoising step.
+
+---
+
+## The Four Phases
+
+### Phase 1: Research Brief Generation
+
+Transform user query into detailed research brief with:
+- Core research question
+- Key sub-questions to explore
+- Expected deliverables and scope
+- Success criteria
+
+**Purpose:** Ensures all downstream research is grounded in explicit requirements.
+
+### Phase 2: Initial Draft Generation
+
+Generate a draft from the LLM's **internal knowledge only**—no external information retrieval.
+
+**Characteristics:**
+- May contain outdated information (training data cutoff)
+- Gaps marked with "[NEEDS RESEARCH]" placeholders
+- Uncertain claims that need verification
+- Incomplete sections that need expansion
+
+**This is intentional—the "noise" that will be "denoised" through research.**
+
+### Phase 3: Diffusion Loop (Supervisor Subgraph)
+
+The core innovation. Each iteration follows four steps:
+
+1. **Generate Research Questions:** Identify gaps in the draft
+2. **Conduct Research:** Retrieve external info for "denoising" (parallel sub-agents)
+3. **Refine Draft:** Remove "noise" (imprecision, incompleteness)
+4. **Assess:** Are findings comprehensive? (NOT draft appearance!)
+
+**Termination Criteria (priority order):**
+1. Gap-closed: Diverse queries yield no new findings
+2. Iteration cap: Hard stop at 15 supervisor iterations
+3. Supervisor override: Allowed only with rationale tied to evidence coverage
+
+### Phase 4: Final Report Generation
+
+Apply quality optimization:
+- **Insightfulness Rules:** Granular breakdowns, detailed mapping tables, nuanced discussion
+- **Helpfulness Rules:** Proper citations, markdown formatting, clear structure
+- Deduplicate findings by URL
+- Generate final deliverable
+
+---
+
+## Supervisor-SubAgent Architecture
+
+### Supervisor Agent
+
+The supervisor orchestrates the diffusion loop:
+- Analyzes current draft state
+- Identifies knowledge gaps
+- Delegates research to sub-agents (parallel)
+- Integrates findings back into draft
+- Decides when research is complete
+
+**Tools available:**
+- `conduct_research` - Spawn parallel sub-agents
+- `refine_draft` - Update draft with new findings
+- `think` - Internal reflection
+- `research_complete` - Signal completion
+
+### Sub-Agent Architecture
+
+Each sub-researcher is a complete agent with its own tool loop:
+
+**Context:** Receives only the topic (no visibility into other agents' work)
+
+**Tools available:**
+- `search` - Web search via Brave API
+- `fetch` - Fetch and summarize a specific URL
+- `read_document` - Read PDF, DOCX, XLSX files
+- `analyze_csv` - Statistical analysis of CSV data
+- `think` - Internal reflection
+
+**Iteration budget:** Max 5 search calls per sub-agent
+
+**Output:** Compressed research findings with citations
+
+---
+
+## Parallel Execution Pattern
+
+When the supervisor receives multiple `conduct_research` calls:
+
+1. Extract topics from tool calls
+2. Spawn goroutines (one per topic)
+3. Each sub-agent runs independently with isolated context
+4. Wait for all to complete (parallel fan-out)
+5. Aggregate results into supervisor state
+
+**Maximum concurrent:** 3 sub-agents (configurable)
+
+**Key principle:** Sub-agents cannot see each other's work, preventing cross-contamination and context pollution.
+
+---
+
+## Context Engineering
+
+### The Context Problems
+
+| Problem | Description | Solution |
+|---------|-------------|----------|
+| Context Poisoning | Hallucinations enter context | Draft as verified state |
+| Context Distraction | Too much context | Parallel isolated agents |
+| Context Confusion | Superfluous context | Structured compression |
+| Context Clash | Disagreeing context | Supervisor resolution |
+
+### Draft as Context Anchor
+
+The draft serves as **persistent, verified context** that:
+- **Evolves incrementally:** Each `refine_draft` call is validated
+- **Structures information:** Prevents disorganized accumulation
+- **Guides research:** Makes gaps explicit
+- **Maintains coherence:** Narrative thread across iterations
+
+### Multi-Agent Context Isolation
+
+Sub-researchers operate with **isolated contexts**:
+- Cannot see each other's work
+- Prevents topic A's findings from biasing topic B
+- Keeps context from growing unboundedly
+- Avoids confusion from interleaved results
+
+---
+
+## Two-Stage Gap Closing
+
+### Stage 1: Information Gap (Diffusion Loop)
+
+**Focus:** What information exists, not how to present it
+
+**Characteristics:**
+- Draft updates are functional, not polished
+- Prioritizes breadth of coverage
+- Uses global-context OR section-specific queries based on gap analysis
+- Completion based on findings, not appearance
+
+### Stage 2: Generation Gap (Final Report)
+
+**Focus:** Presentation, coherence, and user satisfaction
+
+**Characteristics:**
+- All information is available
+- Applies full Insightfulness + Helpfulness rules
+- Generates final deliverable with proper citations
+- Polishes for readability
+
+> "There is a trade-off between the two gaps. We cannot optimize the generation gap too early when the system is still optimizing the information gap because the generation gap tends to bring more verbose and stylistic content that can distract from finding missing information."
+> — Paichun Lin, ThinkDepth.ai
+
+---
+
+## Implementation Details
+
+### From the Python Reference (ThinkDepth.ai)
+
+**Location:** `/go-research/external_code/Deep_Research/`
+
+**Key files:**
+- `multi_agent_supervisor.py` - Supervisor coordination
+- `research_agent.py` - Sub-researcher agent
+- `prompts.py` - All system prompts
+- `state_multi_agent_supervisor.py` - State management
+
+**Supervisor tools:**
+```python
+supervisor_tools = [ConductResearch, ResearchComplete, think_tool, refine_draft_report]
+```
+
+**Iteration limits:**
+```python
+max_researcher_iterations = 15 # Supervisor iterations
+max_concurrent_researchers = 3 # Parallel sub-agents
+```
+
+### From the Go Implementation
+
+**Location:** `/go-research/internal/architectures/think_deep/`
+
+**Key components:**
+- `loop.go` - Main AgentLoop orchestrating all phases
+- `supervisor.go` - Supervisor agent with tool execution
+- `sub_researcher.go` - Sub-agent implementation
+- `prompts.go` - All system prompts
+
+---
+
+## Key Prompts
+
+### Diffusion Algorithm Prompt (Supervisor)
+
+```
+
+1. generate the next research questions to address gaps in the draft report
+2. **conduct_research**: retrieve external information to provide concrete delta for denoising
+3. **refine_draft**: remove "noise" (imprecision, incompleteness) from the draft report
+4. **research_complete**: complete research only based on conduct_research tool's findings'
+ completeness. it should not be based on the draft report.
+
+```
+
+### Compression Prompt (Sub-Agent → Supervisor)
+
+```
+
+**IMPORTANT**: Focus only on substantive research content:
+- **Include**: All search results and findings from web searches
+- **Exclude**: think tool calls and responses - these are internal agent reflections
+- **Focus on**: Actual information gathered from external sources
+
+
+
+1. Output findings should be fully comprehensive and include ALL information verbatim
+2. Include inline citations for each source
+3. Include a "Sources" section at the end with all sources
+Critical: Any information even remotely relevant must be preserved verbatim
+
+```
+
+---
+
+## Benchmark Performance
+
+### RACE Framework (Report Quality)
+
+- **Comprehensiveness:** Coverage breadth and depth
+- **Insight/Depth:** Quality, originality, logic of analysis
+- **Instruction Following:** Adherence to task requirements
+- **Readability:** Clarity, fluency, structure
+
+### FACT Framework (Citation Quality)
+
+- **Citation Accuracy:** % correctly supported
+- **Effective Citations:** Average verified per task
+
+### Results
+
+**Google TTD-DR Performance:**
+- 74.5% win rate vs. OpenAI Deep Research
+- Outperforms by 7.7% on one dataset, 1.7% on another
+
+### Why Diffusion Wins
+
+1. **Iterative refinement catches gaps → Higher Comprehensiveness**
+2. **Parallel execution is efficient → Better Coverage**
+3. **Explicit completion criteria → Validated Comprehensiveness**
+4. **Self-balancing adaptivity → Right-Sized Research**
+5. **Draft as context anchor → Higher Readability**
+6. **Quality rules in final generation → Higher Insight**
+
+---
+
+## Practical Takeaways
+
+1. **Start with a draft** - Reveals gaps faster than blank page
+2. **Deduplicate by URL before synthesis** - Keeps signal high
+3. **Completion is about evidence coverage, not aesthetics**
+4. **Cap iterations and concurrency** - 15 loops, 3 agents max
+5. **Separate information gap from generation gap**
+6. **Isolate sub-agent contexts** - Complete standalone instructions
+7. **Compress findings, preserve everything** - Never summarize
+
+---
+
+## Guardrails
+
+- Require citations for new facts (drop uncited claims)
+- Retry failed tool calls once, then mark as gap
+- Deduplicate by URL before synthesis
+- Completion based on evidence coverage, not draft polish
+
+---
+
+## Sources
+
+- Google Research Blog: https://research.google/blog/deep-researcher-with-test-time-diffusion/
+- Paper: https://arxiv.org/html/2507.16075v1
+- ThinkDepth.ai Implementation: https://github.com/thinkdepthai/Deep_Research
+- Paichun Lin's Analysis: https://paichunlin.substack.com/p/self-balancing-agentic-ai-test-time
+- DeepResearch Bench: https://huggingface.co/spaces/muset-ai/DeepResearch-Bench-Leaderboard
+- My Blog Post: https://addcommitpush.io/blog/diffusion-deep-research
+- Go Implementation: /go-research/internal/architectures/think_deep/
diff --git a/presentations/deep-research/research/foo-cafe.md b/presentations/deep-research/research/foo-cafe.md
new file mode 100644
index 0000000..f1ce7a4
--- /dev/null
+++ b/presentations/deep-research/research/foo-cafe.md
@@ -0,0 +1,151 @@
+# Foo Cafe Malmö - Venue Research
+
+## For Presentation: February 5th, 2026
+
+---
+
+## About Foo Cafe
+
+**Location:** Malmö, Sweden
+**Website:** https://foocafe.org/
+**LinkedIn:** https://se.linkedin.com/company/foocafe
+
+Foo Café is a tech meetup venue operating as a foundation focused on building a happy, supportive tech community. It serves as a neutral meeting space designed as an independent, open forum for knowledge sharing.
+
+---
+
+## Audience Profile
+
+### Typical Attendees
+
+- **Software developers and engineers** (strong Node.js community presence)
+- **Tech entrepreneurs and startup founders**
+- **Technology enthusiasts** from various backgrounds
+- **Data scientists and AI/ML professionals**
+
+### Community Values
+
+- Inclusive: "everybody is invited and no one is excluded"
+- Knowledge sharing focus
+- Personal and professional growth orientation
+
+---
+
+## Presentation Style That Works
+
+### Format Characteristics
+
+- **Casual yet professional approach**
+ - Relaxed enough for genuine networking
+ - Professional enough for technical presentations
+
+- **Interactive format**
+ - Presentations typically include Q&A sessions
+ - Networking/meet-and-eat components
+ - Complementary pizza and drinks encourage informal networking
+
+### Successful Presentation Types
+
+1. **Technical talks** on programming languages and frameworks
+2. **Open source & security topics**
+3. **Data science and AI presentations**
+4. **Startup pitches and demo days**
+5. **Software architecture and emerging technologies**
+6. **Professional development topics**
+
+### Skill Levels
+
+- Presentations at varying skill levels (beginner to advanced)
+- Foo Café provides frameworks to help organize "truly inclusive events"
+
+---
+
+## Venue Vibe
+
+### Atmosphere
+
+- **Community-driven and foundation-based**
+- **Neutral meeting space** for knowledge sharing
+- **Social and relaxed** environment
+- **Growth-oriented** - focused on helping individuals and community learn
+
+### Practical Details
+
+- Daily programming with events year-round
+- Complementary pizza and drinks
+- Space for serious technical content alongside networking
+
+---
+
+## Emil Wåreus's Previous Talks at Foo Cafe
+
+### 1. "The State of AI"
+- Introduction to semantic code search
+- Finding code using natural language
+- Event page: https://foocafe.org/event/state-ai
+
+### 2. "Inside Debricked: Lessons from a Startup's Tech Journey"
+- Structured presentation about startup experience
+- Included Q&A and networking components
+- Event page: https://foocafe.org/event/inside-debricked-lessons-startups-tech-journey
+
+### Other Speaking Experience
+
+Beyond Foo Café, Emil has spoken at major conferences on topics including:
+- Open source security vulnerabilities
+- The cry wolf paradox in security
+- The explosion of open source software's impact on performance
+
+---
+
+## Recommendations for This Presentation
+
+### Based on Venue Research
+
+1. **Start with a relatable hook** - The group project analogy works well for this audience
+2. **Include interactive elements** - Q&A, show of hands, audience questions
+3. **Balance theory with practical demos** - The audience appreciates seeing things work
+4. **Keep it accessible** - Mix of skill levels in audience
+5. **Leave time for networking** - Pizza and drinks conversation is valuable
+
+### Technical Setup
+
+- Arrive early to test projector/screen
+- Have demos pre-loaded and tested
+- Bring backup on USB drive
+- Check API keys are funded for demos
+- Have offline fallback ready
+
+### Engagement Strategies
+
+- Reference previous talks (builds continuity)
+- Connect to local tech community interests
+- Provide practical takeaways people can use
+
+---
+
+## Relevant Context
+
+### Debricked Connection
+
+Emil is Co-founder and Head of Data Science at Debricked:
+- Company focuses on open source security
+- Technical credibility established in community
+- Previous Foo Cafe talks built audience relationship
+
+### Blog Reference
+
+- addcommitpush.io - Emil's technical blog
+- Relevant post: Diffusion Deep Research
+- Can reference as resource for deeper dive
+
+---
+
+## Sources
+
+- About Foo Café: https://foocafe.org/page/about-foo-cafe
+- Foo Café Events: https://foocafe.org/
+- Foo Café LinkedIn: https://se.linkedin.com/company/foocafe
+- Emil at Debricked: https://debricked.com/team/emil-wareus/
+- The State of AI Event: https://foocafe.org/event/state-ai
+- Inside Debricked Event: https://foocafe.org/event/inside-debricked-lessons-startups-tech-journey
diff --git a/presentations/deep-research/research/references.md b/presentations/deep-research/research/references.md
new file mode 100644
index 0000000..87c932f
--- /dev/null
+++ b/presentations/deep-research/research/references.md
@@ -0,0 +1,217 @@
+# References and Sources
+
+## Complete Bibliography for Deep Research Agents Presentation
+
+---
+
+## Academic Papers
+
+### Core Research Papers
+
+#### STORM (Feb 2024)
+- **Title:** STORM: Synthesis of Topic Outlines through Retrieval and Multi-perspective Question Asking
+- **Authors:** Yijia Shao, Yucheng Jiang, Theodore A Kanell, Peter Xu, Omar Khattab, Monica Lam
+- **Venue:** NAACL 2024
+- **arXiv:** 2402.14207
+- **URL:** https://arxiv.org/abs/2402.14207
+- **Project:** https://storm-project.stanford.edu/research/storm/
+
+#### Deep Researcher with Test-Time Diffusion (Jul 2025)
+- **Title:** Deep Researcher with Test-Time Diffusion
+- **Organization:** Google DeepMind / Google Research
+- **arXiv:** 2507.16075
+- **Paper URL:** https://arxiv.org/html/2507.16075v1
+- **Blog:** https://research.google/blog/deep-researcher-with-test-time-diffusion/
+
+#### Chain-of-Thought Prompting (Jan 2022)
+- **Title:** Chain-of-Thought Prompting Elicits Reasoning in Large Language Models
+- **Authors:** Jason Wei, Xuezhi Wang, et al.
+- **Organization:** Google
+- **arXiv:** 2201.11903
+- **URL:** https://arxiv.org/abs/2201.11903
+
+#### ReAct (Oct 2022)
+- **Title:** ReAct: Synergizing Reasoning and Acting in Language Models
+- **Authors:** Shunyu Yao et al.
+- **Organization:** Google Research
+- **Venue:** ICLR 2023
+- **arXiv:** 2210.03629
+- **URL:** https://arxiv.org/abs/2210.03629
+
+#### ToolLLM (Jul 2023)
+- **Title:** ToolLLM: Facilitating Large Language Models to Master 16000+ Real-world APIs
+- **Authors:** Yujia Qin et al.
+- **Organizations:** Alibaba, Stanford
+- **arXiv:** 2307.16789
+- **URL:** https://arxiv.org/abs/2307.16789
+
+### Survey Papers
+
+#### Deep Research: A Survey of Autonomous Research Agents (Aug 2025)
+- **Authors:** Wenlin Zhang et al.
+- **arXiv:** 2508.12752
+- **URL:** https://arxiv.org/abs/2508.12752
+
+#### Deep Research Agents: A Systematic Examination And Roadmap (Jun 2025)
+- **arXiv:** 2506.18096
+- **URL:** https://arxiv.org/abs/2506.18096
+
+#### AgentOrchestra (2025)
+- **Organization:** Skywork AI
+- **URL:** https://arxiv.org/html/2506.12508v1
+
+---
+
+## GitHub Repositories
+
+### Official Implementations
+
+#### STORM (Stanford)
+- **URL:** https://github.com/stanford-oval/storm
+- **Language:** Python
+- **Status:** Active, well-maintained
+
+#### GPT Researcher
+- **URL:** https://github.com/assafelovic/gpt-researcher
+- **Documentation:** https://docs.gptr.dev/docs/gpt-researcher/getting-started/introduction
+- **Language:** Python
+
+#### ThinkDepth.ai Deep Research
+- **URL:** https://github.com/thinkdepthai/Deep_Research
+- **Language:** Python
+- **Note:** Reference implementation for diffusion deep research
+
+#### Skywork DeepResearchAgent
+- **URL:** https://github.com/SkyworkAI/DeepResearchAgent
+- **Language:** Python
+
+### My Implementation
+
+#### Go Research
+- **URL:** https://github.com/emilwareus/addcommitpush.io/tree/main/go-research
+- **Language:** Go
+- **Features:** STORM, Fast, ThinkDeep (diffusion) architectures
+- **Architectures:** /go-research/internal/architectures/
+
+---
+
+## Blog Posts and Articles
+
+### Technical Analysis
+
+#### Google Research Blog
+- **Title:** Deep Researcher with Test-Time Diffusion
+- **URL:** https://research.google/blog/deep-researcher-with-test-time-diffusion/
+- **Date:** July 2025
+
+#### Paichun Lin (ThinkDepth.ai)
+- **Title:** Self-Balancing Agentic AI: Test-Time Diffusion and Context Engineering Re-imagined
+- **URL:** https://paichunlin.substack.com/p/self-balancing-agentic-ai-test-time
+
+#### My Blog Post
+- **Title:** Diffusion Deep Research
+- **URL:** https://addcommitpush.io/blog/diffusion-deep-research
+- **Repository:** Components in /components/blog-posts/diffusion-deep-research.tsx
+
+### Product Announcements
+
+#### OpenAI
+- **Title:** Introducing Deep Research
+- **URL:** https://openai.com/index/introducing-deep-research/
+- **Date:** February 2025
+
+#### Perplexity AI
+- **Title:** Introducing Perplexity Deep Research
+- **URL:** https://www.perplexity.ai/hub/blog/introducing-perplexity-deep-research
+
+#### Atlassian
+- **Title:** Rovo Deep Research v2
+- **URL:** https://www.atlassian.com/blog/artificial-intelligence/rovo-deep-research-v2
+- **Product:** https://www.atlassian.com/software/rovo
+
+#### Tavily
+- **URL:** https://www.tavily.com/
+- **Blog:** https://blog.tavily.com/research-en/
+
+---
+
+## Benchmarks and Evaluation
+
+### DeepResearch Bench
+- **Leaderboard:** https://huggingface.co/spaces/muset-ai/DeepResearch-Bench-Leaderboard
+- **Documentation:** https://deepresearch-bench.github.io/
+- **Components:** RACE (report quality), FACT (citation quality)
+
+---
+
+## Foundational Works
+
+### The Bitter Lesson
+- **Author:** Richard Sutton
+- **Date:** 2019
+- **URL:** http://www.incompleteideas.net/IncIdeas/BitterLesson.html
+- **Relevance:** Foundational thinking on scaling and compute
+
+---
+
+## Framework Comparisons
+
+### LangGraph vs CrewAI
+- **URL:** https://www.zenml.io/blog/langgraph-vs-crewai
+- **Relevance:** Multi-agent framework comparison
+
+---
+
+## This Repository
+
+### Key Files for Reference
+
+#### STORM Implementation
+- `/go-research/external_code/storm/` - Stanford's Python implementation
+- `/go-research/internal/architectures/storm/` - My Go implementation
+
+#### Diffusion Implementation
+- `/go-research/external_code/Deep_Research/` - ThinkDepth.ai Python reference
+- `/go-research/internal/architectures/think_deep/` - My Go implementation
+
+#### Blog Post Content
+- `/components/blog-posts/diffusion-deep-research.tsx` - Full blog post
+- `/components/animations/diffusion/` - Infographic components
+
+#### Documentation
+- `/go-research/README.md` - Go implementation documentation
+
+---
+
+## Citation Format
+
+For academic-style citations in the presentation:
+
+```
+[1] Shao et al. "STORM: Synthesis of Topic Outlines through Retrieval and Multi-perspective Question Asking." NAACL 2024. arXiv:2402.14207
+
+[2] Google DeepMind. "Deep Researcher with Test-Time Diffusion." July 2025. arXiv:2507.16075
+
+[3] Wei et al. "Chain-of-Thought Prompting Elicits Reasoning in Large Language Models." January 2022. arXiv:2201.11903
+
+[4] Yao et al. "ReAct: Synergizing Reasoning and Acting in Language Models." ICLR 2023. arXiv:2210.03629
+```
+
+---
+
+## Download/Access Notes
+
+### Papers Available Directly
+- All arXiv papers are freely accessible
+- Links provided are to official sources
+
+### Implementation Access
+- STORM: MIT License, openly available
+- GPT Researcher: MIT License, openly available
+- ThinkDepth.ai: Open source reference
+- My Go implementation: In this repository
+
+### Commercial Products
+- OpenAI Deep Research: Requires Pro/Plus subscription
+- Perplexity Deep Research: Requires Pro subscription
+- Atlassian Rovo: Enterprise product
diff --git a/presentations/deep-research/research/storm.md b/presentations/deep-research/research/storm.md
new file mode 100644
index 0000000..57ea73b
--- /dev/null
+++ b/presentations/deep-research/research/storm.md
@@ -0,0 +1,260 @@
+# STORM Architecture Deep Dive
+
+## Synthesis of Topic Outlines through Retrieval and Multi-perspective Question Asking
+
+---
+
+## Overview
+
+STORM is a research methodology developed by Stanford University's OVAL Lab that produces comprehensive, well-sourced reports through multi-perspective conversation simulation.
+
+**Paper:** arXiv:2402.14207 (February 2024, NAACL 2024)
+**Authors:** Yijia Shao, Yucheng Jiang, Theodore A Kanell, Peter Xu, Omar Khattab, Monica Lam
+**Repository:** https://github.com/stanford-oval/storm
+
+---
+
+## Core Concept
+
+STORM models the "pre-writing" phase of research that human writers naturally follow:
+1. Research the topic from multiple perspectives
+2. Identify key questions and knowledge gaps
+3. Organize information into a coherent outline
+4. Generate the final article
+
+The key innovation is simulating **multi-perspective conversations** where different "expert personas" research the same topic from their unique viewpoints.
+
+---
+
+## The Four Phases
+
+### Phase 1: DISCOVER (Perspective Generation)
+
+**What happens:**
+- Survey related topics via web search
+- LLM identifies 3-6 expert perspectives
+- Each perspective gets: Name, Focus Area, Initial Questions
+
+**Example perspectives for "Cloud Security Sandboxing":**
+1. Cloud Security Architect - Multi-tenant isolation, threat containment
+2. Performance Engineer - Startup latency optimization, resource management
+3. GCP Platform Specialist - GCP-native implementation patterns
+4. DevSecOps Engineer - Secure CI/CD integration, immutable infrastructure
+
+**Code location:** `knowledge_storm/storm_wiki/modules/persona_generator.py`
+
+### Phase 2: CONVERSE (Parallel Conversation Simulation)
+
+**What happens:**
+- For each perspective, simulate a conversation between:
+ - **WikiWriter:** Asks questions based on the persona's focus
+ - **TopicExpert:** Converts questions → search queries, executes searches, synthesizes answers with citations
+
+**Conversation flow:**
+1. WikiWriter asks a question based on perspective's focus
+2. TopicExpert converts question to search queries
+3. TopicExpert executes web searches
+4. TopicExpert synthesizes answer with inline citations
+5. WikiWriter asks follow-up questions or says "Thank you for your help!"
+6. Repeat until conversation ends
+
+**Key feature:** Conversations run in PARALLEL across perspectives
+
+**Code location:** `knowledge_storm/storm_wiki/modules/knowledge_curation.py`
+
+### Phase 3: ANALYZE (Fact Extraction & Validation)
+
+**What happens:**
+- Extract all facts from conversations
+- Detect contradictions between perspectives
+- Identify knowledge gaps
+- Fill gaps with targeted searches
+
+**Output:** `StormInformationTable` containing all validated facts with sources
+
+**Code location:** Part of `knowledge_curation.py`
+
+### Phase 4: SYNTHESIZE (Two-Phase Outline & Article Generation)
+
+**What happens:**
+1. **Draft outline** from conversation content
+2. **Refine outline** for coherence and logical flow
+3. **Generate full article** with inline citations
+4. **Polish article** for readability
+
+**Output:** Wikipedia-style long-form article with proper citations
+
+**Code locations:**
+- `knowledge_storm/storm_wiki/modules/outline_generation.py`
+- `knowledge_storm/storm_wiki/modules/article_generation.py`
+- `knowledge_storm/storm_wiki/modules/article_polish.py`
+
+---
+
+## Architecture Diagram
+
+```
+┌─────────────────────────────────────────────────────────────────┐
+│ 1. DISCOVER │
+│ - Survey related topics via web search │
+│ - LLM identifies 3-6 expert perspectives │
+│ - Each gets: Name, Focus, Initial Questions │
+└─────────────────────────────────────────────────────────────────┘
+ │
+ ▼
+┌─────────────────────────────────────────────────────────────────┐
+│ 2. CONVERSE (parallel per perspective) │
+│ For each perspective, simulate a conversation: │
+│ WikiWriter: Asks questions based on persona │
+│ TopicExpert: Converts questions → search queries │
+│ Executes web searches │
+│ Synthesizes answers with citations │
+│ Loop until "Thank you for your help!" │
+└─────────────────────────────────────────────────────────────────┘
+ │
+ ▼
+┌─────────────────────────────────────────────────────────────────┐
+│ 3. ANALYZE │
+│ - Extract all facts from conversations │
+│ - Detect contradictions between perspectives │
+│ - Identify knowledge gaps │
+│ - Fill gaps with targeted searches │
+└─────────────────────────────────────────────────────────────────┘
+ │
+ ▼
+┌─────────────────────────────────────────────────────────────────┐
+│ 4. SYNTHESIZE (Two-Phase Outline) │
+│ a. Draft outline from conversation content │
+│ b. Refine outline for coherence │
+│ c. Generate full report with inline citations │
+└─────────────────────────────────────────────────────────────────┘
+```
+
+---
+
+## Configuration Options
+
+From `STORMWikiRunnerArguments`:
+
+| Parameter | Default | Description |
+|-----------|---------|-------------|
+| max_conv_turn | 3 | Maximum questions in conversational Q&A |
+| max_perspective | 3 | Maximum number of perspectives |
+| max_search_queries_per_turn | 3 | Search queries per conversation turn |
+| search_top_k | 3 | Top K search results to consider |
+| retrieve_top_k | 3 | Top K references for each section |
+| max_thread_num | 10 | Maximum parallel threads |
+
+### Perspective Scaling
+
+| Complexity | Perspectives | Use Case |
+|------------|--------------|----------|
+| Simple | 2-3 | Factual queries with limited scope |
+| Moderate | 3-4 | Multi-aspect topics needing diverse views |
+| Complex | 5-6 | Deep research requiring comprehensive coverage |
+
+---
+
+## LLM Configuration
+
+STORM uses different LLMs for different phases:
+
+```python
+class STORMWikiLMConfigs:
+ conv_simulator_lm # Conversation simulation (except questions)
+ question_asker_lm # Question generation
+ outline_gen_lm # Outline generation
+ article_gen_lm # Article generation
+ article_polish_lm # Final polishing
+```
+
+Default models (OpenAI):
+- Conversation: gpt-4o-mini-2024-07-18
+- Outline: gpt-4-0125-preview
+- Article: gpt-4o-2024-05-13
+- Polish: gpt-4o-2024-05-13
+
+---
+
+## Go Implementation (in this repo)
+
+The go-research package includes a STORM implementation:
+
+**Location:** `/go-research/internal/architectures/storm/`
+
+**Key differences from Python:**
+- Uses OpenRouter as LLM provider
+- Brave Search for web retrieval
+- Streaming output during conversations
+- Session persistence to JSON + Obsidian vault
+
+**Usage:**
+```bash
+cd go-research
+go run ./cmd/research
+
+# In REPL:
+research> /storm How do modern LLM agents work?
+```
+
+---
+
+## Performance Characteristics
+
+From the NAACL 2024 paper:
+
+- **Organization:** 25% improvement over outline-driven baselines
+- **Coverage:** 10% improvement over outline-driven baselines
+- **FActScore:** Comparable to human-written Wikipedia articles
+
+**Strengths:**
+- Multi-perspective ensures diverse viewpoint coverage
+- Conversation simulation generates high-quality questions
+- Two-phase outline prevents incoherent structure
+
+**Weaknesses:**
+- Linear pipeline can't self-correct early errors
+- No explicit handling of contradictory sources
+- Fixed number of perspectives regardless of topic complexity
+
+---
+
+## Key Code Components
+
+### Python (stanford-oval/storm)
+
+```
+knowledge_storm/
+├── storm_wiki/
+│ ├── engine.py # STORMWikiRunner - main orchestrator
+│ └── modules/
+│ ├── persona_generator.py # Phase 1: Perspective generation
+│ ├── knowledge_curation.py # Phase 2-3: Conversations & analysis
+│ ├── outline_generation.py # Phase 4a: Outline generation
+│ ├── article_generation.py # Phase 4b: Article generation
+│ └── article_polish.py # Phase 4c: Final polish
+```
+
+### Go (this repo)
+
+```
+go-research/internal/
+├── architectures/storm/ # STORM implementation
+├── agents/
+│ ├── conversation.go # WikiWriter↔TopicExpert simulation
+│ ├── analysis.go # Fact validation & gap detection
+│ └── synthesis.go # Two-phase outline & report
+├── orchestrator/
+│ └── deep_storm.go # Main STORM flow
+└── planning/
+ └── perspective.go # Perspective generation
+```
+
+---
+
+## Sources
+
+- Original Paper: https://arxiv.org/abs/2402.14207
+- Project Page: https://storm-project.stanford.edu/research/storm/
+- GitHub: https://github.com/stanford-oval/storm
+- Go Implementation: /go-research/internal/architectures/storm/
diff --git a/presentations/deep-research/research/timeline.md b/presentations/deep-research/research/timeline.md
new file mode 100644
index 0000000..40bd687
--- /dev/null
+++ b/presentations/deep-research/research/timeline.md
@@ -0,0 +1,222 @@
+# Deep Research Agents Timeline
+
+## Comprehensive History from Foundations to Modern Systems
+
+---
+
+## FOUNDATIONAL LAYER (2021-2023)
+
+### Chain-of-Thought Prompting
+- **Date:** January 28, 2022
+- **Organization:** Google
+- **Authors:** Jason Wei, Xuezhi Wang, Dale Schuurmans, Maarten Bosma, Brian Ichter, Fei Xia, Ed Chi, Quoc Le, Denny Zhou
+- **Paper:** arXiv:2201.11903
+- **URL:** https://arxiv.org/abs/2201.11903
+- **Key Innovation:** Generating intermediate reasoning steps significantly improves LLM performance on complex reasoning tasks
+- **Impact:** Foundational work showing that step-by-step reasoning improves LLM capabilities; became a building block for all subsequent agentic research systems
+
+### ReAct: Reasoning and Acting
+- **Date:** October 2022 (Published at ICLR 2023)
+- **Organization:** Google Research
+- **Authors:** Shunyu Yao and 6 colleagues
+- **Paper:** arXiv:2210.03629
+- **URL:** https://arxiv.org/abs/2210.03629
+- **Key Innovation:** Interleaved reasoning traces and task-specific actions, allowing LLMs to generate both reasoning and actions in an alternating manner
+- **How It Works:** Agents gather additional information from external sources (e.g., Wikipedia) and use that to improve reasoning
+- **Impact:** First pattern to demonstrate synergy between reasoning and action-taking; enables dynamic interaction with external environments. Foundation for modern research agents
+
+### ToolLLM
+- **Date:** July 2023
+- **Organization:** Alibaba, Stanford
+- **Authors:** Yujia Qin et al.
+- **Paper:** arXiv:2307.16789
+- **URL:** https://arxiv.org/abs/2307.16789
+- **Key Innovation:** Framework for teaching LLMs to master 16,000+ real-world APIs
+- **How It Works:** Includes ToolBench instruction-tuning dataset automatically constructed using ChatGPT for tool use
+- **Impact:** Systematically catalogs and trains models on massive API ecosystems; enables specialized tool-use capabilities at scale
+
+---
+
+## EARLY RESEARCH AGENT SYSTEMS (2023-2024)
+
+### GPT Researcher
+- **Date:** 2023 (Formalized in 2024)
+- **Organization:** Open Source Community (Evolved into Tavily)
+- **Creator:** Assaf Elovic
+- **Repository:** https://github.com/assafelovic/gpt-researcher
+- **Documentation:** https://docs.gptr.dev/docs/gpt-researcher/getting-started/introduction
+- **Key Innovation:** Multi-agent architecture with "planner" and "execution" agents
+- **How It Works:**
+ 1. Planner generates research questions
+ 2. Execution agents search for related information based on each question
+ 3. Planner aggregates results into a comprehensive report
+- **Performance:** Generates 5-6 page reports in ~3 minutes for ~$0.005
+- **Impact:** Early open-source deep research agent; modular design allowing custom LLMs and search engines
+
+### STORM: Synthesis of Topic Outlines through Retrieval and Multi-perspective Question Asking
+- **Date:** February 22, 2024 (arXiv v1), April 8, 2024 (v2)
+- **Organization:** Stanford University (OVAL Lab)
+- **Authors:** Yijia Shao, Yucheng Jiang, Theodore A Kanell, Peter Xu, Omar Khattab, Monica Lam
+- **Conference:** NAACL 2024
+- **Paper:** arXiv:2402.14207
+- **URLs:**
+ - Paper: https://arxiv.org/abs/2402.14207
+ - Project: https://storm-project.stanford.edu/research/storm/
+ - GitHub: https://github.com/stanford-oval/storm
+- **Key Innovation:** Multi-perspective research through simulated conversations with retrieval-augmented question-answering
+- **How It Works:**
+ 1. **DISCOVER:** Survey related topics, generate 3-6 expert perspectives
+ 2. **CONVERSE:** Parallel WikiWriter↔TopicExpert dialogues
+ 3. **ANALYZE:** Extract facts, detect contradictions, fill gaps
+ 4. **SYNTHESIZE:** Two-phase outline → final report with citations
+- **Performance:** 25% improvement in organization and 10% improvement in coverage vs. outline-driven baselines
+- **Impact:** Focuses on multi-perspective research and outline generation; emphasizes diverse viewpoint synthesis
+
+---
+
+## COMMERCIAL RESEARCH AGENTS (2024-2025)
+
+### OpenAI Deep Research
+- **Date:** February 2-3, 2025
+- **Organization:** OpenAI
+- **Announcement:** https://openai.com/index/introducing-deep-research/
+- **Key Innovation:** Autonomous research mode integrated into ChatGPT
+- **How It Works:** Conducts multi-turn informational research through dynamic planning and retrieval. Generates comprehensive analytical reports grounded in web-based evidence
+- **Impact:** Integrated into ChatGPT Pro/Plus; industry-standard benchmark for deep research performance; initial focus on enterprise-grade analysis
+
+### Perplexity Deep Research
+- **Date:** 2024-2025
+- **Organization:** Perplexity AI
+- **Availability:** Part of Perplexity Pro
+- **URL:** https://www.perplexity.ai/hub/blog/introducing-perplexity-deep-research
+- **Key Innovation:** Test-time compute (TTC) architecture
+- **How It Works:**
+ 1. Planning agent creates step-by-step research guide
+ 2. Search queries generated and executed for each step
+ 3. Results flow between sequential steps
+ 4. Uses "test time compute" expansion framework mimicking human cognitive processes
+- **Performance:** 2-4 minute execution time
+- **Impact:** TTC architecture enabling systematic exploration of complex topics; combines search and coding capabilities
+
+### Tavily Research Agent
+- **Date:** 2024-2025
+- **Organization:** Tavily (Spun out of GPT Researcher)
+- **Funding:** Series A $20M (2025), Total $25M
+- **URL:** https://www.tavily.com/
+- **Key Innovation:** Enterprise-grade web search layer for AI agents
+- **How It Works:** Supplies fast, real-time web data through agent-first APIs. Developed "Company Researcher" tool using LangGraph workflow with Tavily Search and Extract
+- **Performance:** #1 ranking on DeepResearch Bench
+- **Impact:** Optimized for RAG purposes; Fast and Ultra Fast search depths minimizing latency
+
+### Google Deep Researcher with Test-Time Diffusion (TTD-DR)
+- **Date:** July 2025
+- **Organization:** Google DeepMind / Google Research
+- **Model:** Gemini 2.5 Pro
+- **Paper:** arXiv:2507.16075
+- **URLs:**
+ - Blog: https://research.google/blog/deep-researcher-with-test-time-diffusion/
+ - Paper: https://arxiv.org/html/2507.16075v1
+- **Key Innovation:** Models research report writing as a diffusion process
+- **How It Works:** Messy first drafts are gradually polished into high-quality final versions through:
+ 1. Component-wise optimization via self-evolution
+ 2. Report-level refinement via denoising with retrieval
+- **Performance:** 74.5% win rate vs. OpenAI DR; outperforms by 7.7% on one dataset, 1.7% on another
+- **Impact:** First to model report generation as diffusion process; novel approach treating research as iterative refinement rather than linear pipeline
+
+### Atlassian Rovo Deep Research v2
+- **Date:** 2025
+- **Organization:** Atlassian
+- **URLs:**
+ - Blog: https://www.atlassian.com/blog/artificial-intelligence/rovo-deep-research-v2
+ - Product: https://www.atlassian.com/software/rovo
+- **Key Innovation:** Orchestrated agent architecture with organizational knowledge integration
+- **How It Works:**
+ 1. Clarifies brief with targeted questions
+ 2. Proposes structured plan for user approval/editing
+ 3. Executes research across internal knowledge and public web
+ 4. Synthesizes cited executive-ready reports
+- **Impact:** Focuses on organizational knowledge integration across Atlassian and connected SaaS apps; emphasizes user control through interactive planning stage
+
+---
+
+## ADVANCED MULTI-AGENT ARCHITECTURES (2025)
+
+### Skywork DeepResearchAgent / AgentOrchestra
+- **Date:** 2025
+- **Organization:** Skywork AI, Nanyang Technological University
+- **Authors:** Skywork AI Research Team
+- **GitHub:** https://github.com/SkyworkAI/DeepResearchAgent
+- **Paper:** https://arxiv.org/html/2506.12508v1 (AgentOrchestra)
+- **Key Innovation:** Hierarchical multi-agent system with top-level planning agent
+- **How It Works:**
+ - Top-level planning agent coordinates specialized lower-level agents
+ - Agents include: Deep Analyzer, Deep Researcher, Browser Use Agent, MCP Manager
+ - Breaks tasks into sub-tasks, assigns to agents, dynamically coordinates collaboration
+- **Performance:**
+ - 83.39 average test performance
+ - 93.55 on Level 1
+ - 83.02 on Level 2
+ - 65.31 on Level 3
+ - Outperforms on SimpleQA, GAIA, HLE benchmarks
+- **Impact:** Hierarchical orchestration paradigm; dynamic task decomposition; excels at complex reasoning requiring external tools
+
+---
+
+## ARCHITECTURAL PATTERN: Plan-Research-Report
+
+This pattern emerged across multiple implementations as a standard approach:
+
+### Core Pattern Flow:
+1. **Planning Phase:** LLM breaks user objective into 3-7 crisp, self-contained sub-questions; assigns to specialized agents
+2. **Research/Execution Phase:** Source Finder agent with web search tool returns high-signal links with titles, URLs, summaries, content
+3. **Processing Phase:** Summarization agent extracts relevant facts; Reviewer scans coverage and flags gaps; proposes new questions if needed
+4. **Report Generation:** Professional Research Writer synthesizes structured, readable report
+
+### Implementations:
+- OpenAI Deep Research
+- Perplexity Deep Research
+- Anthropic's multi-agent research system
+- Numerous others
+
+### Key Insight:
+This pattern has become the de facto standard for modern research automation because it separates concerns (planning vs. execution vs. synthesis) and enables iterative refinement.
+
+---
+
+## SURVEY PAPERS (2025)
+
+### Deep Research: A Survey of Autonomous Research Agents
+- **Date:** August 2025
+- **Authors:** Wenlin Zhang et al.
+- **Paper:** arXiv:2508.12752
+- **URL:** https://arxiv.org/abs/2508.12752
+- **Scope:** Systematic overview of deep research pipeline (planning, question developing, web exploration, report generation); comparison with RAG and tool-use systems
+
+### Deep Research Agents: A Systematic Examination And Roadmap
+- **Date:** June 2025
+- **Paper:** arXiv:2506.18096
+- **URL:** https://arxiv.org/abs/2506.18096
+- **Scope:** Comprehensive examination of DR agents as new category of autonomous systems; discusses dynamic reasoning, adaptive planning, multi-hop retrieval, tool use, structured report generation; industry implementations
+
+---
+
+## KEY EVOLUTION INSIGHTS
+
+### From Static to Dynamic:
+- **Early systems (2021-2023):** Static prompts, hard-coded workflows
+- **Recent systems (2024-2025):** Adaptive agentic paradigms, dynamic planning, real-time interaction
+
+### Core Pipeline Standardization:
+All modern deep research agents follow variants of: **Plan → Research → Report**
+
+### Architectural Trends:
+1. **Modular agents** with specialized roles (searcher, analyzer, writer, reviewer)
+2. **Hierarchical coordination** (planning agents managing execution agents)
+3. **Iterative refinement** (draft → review → revise → finalize)
+4. **Integrated tooling** (web search, code execution, document processing, MCP support)
+
+### Performance Metrics:
+- Report generation: 3-10 minutes
+- Cost: $0.005-$0.10 per research task
+- Win rates: 74.5% (Google TTD-DR vs OpenAI DR)
+- Benchmark improvements: 7-10% over baselines
diff --git a/presentations/deep-research/slides.md b/presentations/deep-research/slides.md
new file mode 100644
index 0000000..eefda7f
--- /dev/null
+++ b/presentations/deep-research/slides.md
@@ -0,0 +1,611 @@
+# Deep Research Agents - Architecture Walkthrough
+## Slide Deck with Speaker Notes
+
+**Event:** Foo Cafe Malmö | February 5th, 2026
+**Speaker:** Emil Wåreus
+**Total Duration:** ~60-70 minutes (including demos and Q&A)
+
+---
+
+## SLIDE 1: Title + Hook
+**Duration:** 2 minutes
+
+### Visual
+```
+┌────────────────────────────────────────────────────────────────────┐
+│ │
+│ [Cover image: /public/posts/diffusion-deep-research/ │
+│ cover-optimized.webp] │
+│ │
+│ DEEP RESEARCH AGENTS │
+│ Architecture Walkthrough │
+│ │
+│ Emil Wåreus │
+│ Foo Cafe Malmö | Feb 5, 2026 │
+│ │
+│ ───────────────────────────────────────────────────────────────── │
+│ │
+│ 🎓 Remember group projects where everyone wrote in isolation? │
+│ Then you "glued it together" 3 hours before deadline? │
+│ │
+│ Result: Repetitive, inconsistent, different quality... │
+│ │
+│ This is exactly how most AI research agents work today. │
+│ │
+└────────────────────────────────────────────────────────────────────┘
+```
+
+### Speaker Notes
+"Welcome everyone! Quick show of hands:
+
+- Who's used ChatGPT or Claude for research? [most hands]
+- Who's noticed it getting repetitive or inconsistent in long outputs? [many hands]
+
+That problem? It's the same as those school group projects where everyone wrote their section alone, then you 'glued it together' at the last minute.
+
+Today I'll show you how we fixed this - and yes, it involves the same math that powers image AI like DALL-E."
+
+---
+
+## SLIDE 2: Timeline - The Evolution
+**Duration:** 5 minutes
+
+### Visual
+```
+┌────────────────────────────────────────────────────────────────────┐
+│ │
+│ The Evolution of Research Agents (2022-2025) │
+│ │
+│ 2022 ════════════════════════════════════════════════════════════ │
+│ │ Chain-of-Thought (Google) → "Show your work" │
+│ │ ReAct (Google) → Reasoning + Acting together │
+│ │ │
+│ 2023 ════════════════════════════════════════════════════════════ │
+│ │ GPT Researcher → First popular open-source agent │
+│ │ │
+│ 2024 ════════════════════════════════════════════════════════════ │
+│ │ STORM (Stanford) ⭐ → Multi-perspective conversations │
+│ │ │
+│ 2025 ════════════════════════════════════════════════════════════ │
+│ │ OpenAI Deep Research → Commercial benchmark │
+│ │ Perplexity Deep Research → Test-time compute │
+│ │ Google TTD-DR ⭐ → Diffusion approach (74.5% win rate!) │
+│ │ │
+│ ══════════════════════════════════════════════════════════════════ │
+│ │
+│ Pattern: Single calls → Agents → Multi-agent → Iterative │
+│ │
+└────────────────────────────────────────────────────────────────────┘
+```
+
+### Speaker Notes
+"Quick history - this field moves FAST.
+
+2022: Google showed LLMs can 'think' step-by-step (Chain-of-Thought) and combine reasoning with tools (ReAct). Birth of agents.
+
+2023: GPT Researcher made it accessible - open source, anyone could run it.
+
+2024: Stanford's STORM simulated expert conversations from multiple perspectives. We'll demo this.
+
+2025: The commercial wave hit. OpenAI, Perplexity launched products. But Google did something different - they treated research like image generation.
+
+That diffusion approach? 74.5% win rate against OpenAI. We'll demo that too.
+
+The pattern: we went from single LLM calls, to agents, to multi-agent, to iterative refinement. More self-correction = better results."
+
+---
+
+## SLIDE 3: STORM Architecture
+**Duration:** 4 minutes
+
+### Visual
+```
+┌────────────────────────────────────────────────────────────────────┐
+│ │
+│ STORM: Multi-Perspective Research (Stanford, 2024) │
+│ │
+│ "What if we simulated expert conversations about a topic?" │
+│ │
+│ ┌──────────────────────────────────────────────────────────────┐ │
+│ │ │ │
+│ │ 1. DISCOVER → Search related topics → 3 expert personas │ │
+│ │ + 1 default "Basic fact writer" │ │
+│ │ │ │
+│ │ 2. INTERVIEW → Parallel: WikiWriter ↔ TopicExpert (×3 turns)│ │
+│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
+│ │ │ Fact Writer │ │ AI Ethics │ │ Startup PM │ (||) │ │
+│ │ │ ↔ Expert │ │ ↔ Expert │ │ ↔ Expert │ │ │
+│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
+│ │ TopicExpert: QuestionToQuery → Search → AnswerQuestion │ │
+│ │ with [1],[2],[3] inline citations │ │
+│ │ │ │
+│ │ 3. OUTLINE → Draft (LLM knowledge) → Refine (+ conv data) │ │
+│ │ │ │
+│ │ 4. WRITE → Per-section article writing with citations │ │
+│ │ │ │
+│ │ 5. LEAD → Lead section written AFTER body → Assemble │ │
+│ │ │ │
+│ └──────────────────────────────────────────────────────────────┘ │
+│ │
+│ Linear pipeline — each phase runs exactly once. No backtracking. │
+│ │
+└────────────────────────────────────────────────────────────────────┘
+```
+
+### Speaker Notes
+"STORM's insight: Wikipedia articles are comprehensive because they synthesize MULTIPLE expert viewpoints.
+
+Five phases:
+1. DISCOVER - Search for related content, generate expert personas. Always includes a 'Basic fact writer' for broad coverage.
+2. INTERVIEW - For each persona, a WikiWriter asks questions and a TopicExpert answers with web-searched citations [1],[2]. The TopicExpert first generates search queries, then searches, then synthesizes. All conversations run in PARALLEL.
+3. OUTLINE - Two-stage: draft from LLM knowledge first, then refine with conversation data. Prevents the outline from being biased by whichever expert found the most.
+4. WRITE - Each top-level section is written independently with inline citations.
+5. LEAD - Lead section written AFTER the body so it reflects actual content. Then assembled with references.
+
+Important: this pipeline runs ONCE. No iteration, no backtracking. We'll come back to that.
+
+Let me show you..."
+
+---
+
+## SLIDE 4: STORM Demo
+**Duration:** 6 minutes
+
+### Visual
+```
+┌────────────────────────────────────────────────────────────────────┐
+│ │
+│ 🖥️ LIVE DEMO: STORM │
+│ │
+│ Terminal: Python + LangGraph │
+│ │
+│ ┌──────────────────────────────────────────────────────────────┐ │
+│ │ $ uv run main.py --agent=storm "I am giving a │ │
+│ │ presentation at Foo Café in Malmö about deep research │ │
+│ │ AI agents..." │ │
+│ └──────────────────────────────────────────────────────────────┘ │
+│ │
+│ Watch for: │
+│ ✓ Perspective generation (1 default + 3 generated) │
+│ ✓ Parallel interviews (WikiWriter ↔ TopicExpert, 3 turns each) │
+│ ✓ TopicExpert: QuestionToQuery → Search → AnswerQuestion [1],[2]│
+│ ✓ Two-stage outline (draft → refine with conv data) │
+│ ✓ Per-section article writing with citations │
+│ ✓ Lead section + assembly → final Wikipedia-style article │
+│ │
+└────────────────────────────────────────────────────────────────────┘
+```
+
+### Speaker Notes
+[Run the demo, narrate as it goes]
+Expected: ~75s, ~$0.05, ~48 LLM calls, 60+ sources
+
+"Watch — first it discovers perspectives. 'Basic fact writer' is always there, plus 3 generated experts like 'AI Ethics Scholar' or 'Community Organizer.'
+
+Now the interviews start IN PARALLEL — see multiple WikiWriter/TopicExpert conversations running at once. The TopicExpert generates search queries, searches, then answers with [1],[2] citations.
+
+After 3 turns each, it compiles the interviews, builds a two-stage outline, then writes each section independently.
+
+And finally the lead section, written AFTER the body. Here's the final Wikipedia-style article — diverse coverage, all with citations."
+
+---
+
+## SLIDE 5: The Problem with Linear Pipelines
+**Duration:** 2 minutes
+
+### Visual
+```
+┌────────────────────────────────────────────────────────────────────┐
+│ │
+│ The Problem: Most Agents Are Still Linear │
+│ │
+│ ┌────────┐ ┌─────────────────────────┐ ┌────────────────┐ │
+│ │ PLAN │───►│ PARALLEL RESEARCH │───►│ SYNTHESIZE │ │
+│ └────────┘ │ A B C │ └────────────────┘ │
+│ └─────────────────────────┘ │
+│ │ │ │ │
+│ ▼ ▼ ▼ │
+│ Can't see each other! │
+│ Can't update the plan! │
+│ One pass - no self-correction! │
+│ │
+│ ═══════════════════════════════════════════════════════════════ │
+│ │
+│ ❌ Late discoveries can't influence early decisions │
+│ ❌ Sub-agents work in isolation (group project problem!) │
+│ ❌ No iteration - you hope it works first try │
+│ │
+│ What if the report could EVOLVE? │
+│ │
+└────────────────────────────────────────────────────────────────────┘
+```
+
+### Speaker Notes
+"STORM is great, but it still has the group project problem.
+
+The sub-agents can't see each other's work. If agent B discovers something that should change the plan, too late.
+
+You run it once and hope for the best. No iteration, no self-correction.
+
+What if the report could EVOLVE? What if we could iterate and refine?"
+
+---
+
+## SLIDE 6: Diffusion Deep Research - The Insight
+**Duration:** 3 minutes
+
+### Visual
+```
+┌────────────────────────────────────────────────────────────────────┐
+│ │
+│ Diffusion: Research as Iterative Refinement │
+│ │
+│ ┌─────────────────────────────────────────────────────────────┐ │
+│ │ IMAGE DIFFUSION (DALL-E, Midjourney) │ │
+│ │ │ │
+│ │ [Noise] ──► [Less Noise] ──► [Shape] ──► [Clean Image] │ │
+│ └─────────────────────────────────────────────────────────────┘ │
+│ ↕ Same idea! │
+│ ┌─────────────────────────────────────────────────────────────┐ │
+│ │ RESEARCH DIFFUSION │ │
+│ │ │ │
+│ │ [Rough Draft] ──► [+Research] ──► [Refine] ──► [Report] │ │
+│ └─────────────────────────────────────────────────────────────┘ │
+│ │
+│ ┌────────────────────────┬────────────────────────────────────┐ │
+│ │ Image Diffusion │ Research Diffusion │ │
+│ ├────────────────────────┼────────────────────────────────────┤ │
+│ │ Random noise │ Initial draft (LLM knowledge) │ │
+│ │ Denoising step │ Research iteration + refinement │ │
+│ │ Guidance signal │ Retrieved web information │ │
+│ │ Clean image │ Comprehensive report │ │
+│ └────────────────────────┴────────────────────────────────────┘ │
+│ │
+└────────────────────────────────────────────────────────────────────┘
+```
+
+### Speaker Notes
+"Here's Google's breakthrough.
+
+In image diffusion, you start with random noise and iteratively 'denoise' until you get a clean image.
+
+What if research worked the same way?
+
+Start with a ROUGH DRAFT from the model's internal knowledge - that's your 'noise'. It might have outdated info, gaps, uncertainties.
+
+Then iteratively: find gaps, research, refine. Each iteration 'denoises' the draft.
+
+The key insight: the initial draft IS the noise. We refine it away through iteration."
+
+---
+
+## SLIDE 7: Diffusion Architecture
+**Duration:** 4 minutes
+
+### Visual
+[Use: diffusion-overview component screenshot]
+
+```
+┌────────────────────────────────────────────────────────────────────┐
+│ │
+│ Diffusion Deep Research: Four Phases │
+│ │
+│ ┌────────────────────────────────────────────────────────────┐ │
+│ │ 1. BRIEF │ Transform query → research brief │ │
+│ └────────────────────────────────────────────────────────────┘ │
+│ ▼ │
+│ ┌────────────────────────────────────────────────────────────┐ │
+│ │ 2. DRAFT │ Generate from LLM knowledge ONLY (the "noise") │ │
+│ └────────────────────────────────────────────────────────────┘ │
+│ ▼ │
+│ ┌────────────────────────────────────────────────────────────┐ │
+│ │ 3. LOOP │ Supervisor with tool-calling (max 8 iters): │ │
+│ │ │ → ConductResearch: spawn ReAct sub-agents │ │
+│ │ ⭐ │ → Sub-agents search + compress findings │ │
+│ │ │ → Refine draft with evidence (denoising step) │ │
+│ │ │ → ResearchComplete when findings sufficient │ │
+│ └────────────────────────────────────────────────────────────┘ │
+│ ▼ │
+│ ┌────────────────────────────────────────────────────────────┐ │
+│ │ 4. FINAL │ Apply quality rules, polish, deduplicate │ │
+│ └────────────────────────────────────────────────────────────┘ │
+│ │
+│ ⚠️ CRITICAL: Loop stops when EVIDENCE is complete, │
+│ NOT when the draft looks polished! │
+│ │
+└────────────────────────────────────────────────────────────────────┘
+```
+
+### Speaker Notes
+"Four phases:
+
+1. BRIEF - Transform query into detailed research objectives
+
+2. DRAFT - Generate from LLM knowledge ONLY, higher temperature. No searching yet! This is intentionally speculative — our 'noise'.
+
+3. LOOP - This is the magic. A SUPERVISOR LLM with tool-calling decides what to do:
+ - Calls ConductResearch to spawn ReAct sub-agents (up to 3 parallel)
+ - Each sub-agent runs its own search + think loop, then compresses findings
+ - Draft is refined with the evidence after each batch — this IS the denoising step
+ - Supervisor calls ResearchComplete when it judges findings are comprehensive
+ - Max 8 iterations to cap costs
+
+4. FINAL - Once evidence is gathered, polish into a professional report with citations.
+
+[EMPHASIS] The critical insight: the supervisor checks FINDINGS completeness, not draft appearance. A polished draft can hide missing info. Stop when queries yield no new facts."
+
+---
+
+## SLIDE 8: Parallel Sub-Agents
+**Duration:** 2 minutes
+
+### Visual
+[Use: parallel-agents component screenshot]
+
+```
+┌────────────────────────────────────────────────────────────────────┐
+│ │
+│ Parallel Research with Isolated Contexts │
+│ │
+│ ┌─────────────────┐ │
+│ │ SUPERVISOR │ │
+│ │ Identifies gaps │ │
+│ └────────┬────────┘ │
+│ │ │
+│ ┌────────────────┼────────────────┐ │
+│ ▼ ▼ ▼ │
+│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
+│ │ Sub-Agent │ │ Sub-Agent │ │ Sub-Agent │ │
+│ │ Topic A │ │ Topic B │ │ Topic C │ │
+│ │ │ │ │ │ │ │
+│ │ 🔒 Isolated│ │ 🔒 Isolated│ │ 🔒 Isolated│ │
+│ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ │
+│ └────────────────┼────────────────┘ │
+│ ▼ │
+│ ┌─────────────────┐ │
+│ │ SUPERVISOR │ │
+│ │ Merges findings │ │
+│ │ Refines draft │ │
+│ └─────────────────┘ │
+│ │
+│ Isolation is intentional: prevents cross-contamination │
+│ Each agent needs complete, standalone instructions │
+│ │
+└────────────────────────────────────────────────────────────────────┘
+```
+
+### Speaker Notes
+"When the supervisor calls ConductResearch, it spawns up to 3 ReAct sub-agents in parallel.
+
+Each sub-agent runs its own Think-Act-Observe loop — the same ReAct pattern we saw earlier. They search the web, reflect on what they found, search again, until they have enough.
+
+Then the critical step: findings are COMPRESSED before returning to the supervisor. Raw conversation has tool calls, search results, reflections — too noisy for the supervisor. Compression preserves all facts and source URLs but removes the noise.
+
+The isolation is intentional — prevents cross-contamination. Independent perspectives.
+
+After all sub-agents return, the draft is automatically refined with the new evidence. That's the denoising step."
+
+---
+
+## SLIDE 9: Diffusion Demo
+**Duration:** 7 minutes
+
+### Visual
+```
+┌────────────────────────────────────────────────────────────────────┐
+│ │
+│ 🖥️ LIVE DEMO: DIFFUSION │
+│ │
+│ Terminal: Python + LangGraph │
+│ │
+│ ┌──────────────────────────────────────────────────────────────┐ │
+│ │ $ uv run main.py --agent=diffusion "I am giving a │ │
+│ │ presentation at Foo Café in Malmö about deep research │ │
+│ │ AI agents..." │ │
+│ └──────────────────────────────────────────────────────────────┘ │
+│ │
+│ Watch for: │
+│ ✓ Noisy draft (from LLM knowledge only, temp=0.7) │
+│ ✓ Supervisor tool calls (ConductResearch, think_tool) │
+│ ✓ ReAct sub-agents searching + compressing │
+│ ✓ Draft refinement after each research batch │
+│ ✓ Supervisor iteration count (max 8) │
+│ ✓ ResearchComplete → final polished report │
+│ │
+└────────────────────────────────────────────────────────────────────┘
+```
+
+### Speaker Notes
+[Run the demo, narrate as it goes]
+
+"Watch the initial draft - it's rough, has gaps marked... Now it's identifying what's missing... Spawning sub-agents... See the iteration count going up... The draft is getting more detailed with each pass... And here's the final report - compare how much more comprehensive it is than the initial draft."
+
+---
+
+## SLIDE 10: Why Diffusion Wins
+**Duration:** 3 minutes
+
+### Visual
+[Use: race-metrics component screenshot if available]
+
+```
+┌────────────────────────────────────────────────────────────────────┐
+│ │
+│ Benchmark Results: DeepResearch Bench │
+│ │
+│ ┌──────────────────────────────────────────────────────────────┐ │
+│ │ │ │
+│ │ Google Diffusion vs OpenAI Deep Research │ │
+│ │ │ │
+│ │ 74.5% WIN RATE │ │
+│ │ │ │
+│ │ +7.7% on Dataset 1, +1.7% on Dataset 2 │ │
+│ │ │ │
+│ └──────────────────────────────────────────────────────────────┘ │
+│ │
+│ WHY IT WORKS: │
+│ ┌────────────────────────────┬─────────────────────────────────┐ │
+│ │ Iterative refinement │ Catches gaps single-pass misses │ │
+│ │ Evidence-based completion │ No premature stopping │ │
+│ │ Self-balancing │ Simple=2 iters, Complex=15 │ │
+│ │ Draft as context anchor │ Coherence across iterations │ │
+│ │ Isolated sub-agents │ Independent perspectives │ │
+│ └────────────────────────────┴─────────────────────────────────┘ │
+│ │
+│ Key: Iteration + Self-Correction > Single Pass │
+│ │
+└────────────────────────────────────────────────────────────────────┘
+```
+
+### Speaker Notes
+"The numbers are striking. Google's diffusion beat OpenAI's Deep Research 74.5% of the time.
+
+Why?
+
+1. Iterative refinement catches gaps that single-pass misses
+2. Evidence-based completion means no premature stopping
+3. Self-balancing: simple queries take 2-3 iterations, complex ones take 10-15
+4. The draft anchors context across many iterations
+5. Isolated sub-agents bring independent perspectives
+
+The theme: iteration and self-correction beat single-pass every time."
+
+---
+
+## SLIDE 11: Practical Takeaways
+**Duration:** 3 minutes
+
+### Visual
+```
+┌────────────────────────────────────────────────────────────────────┐
+│ │
+│ 7 Things You Can Apply Today │
+│ │
+│ 1. START WITH A DRAFT │
+│ Even rough - reveals gaps faster than blank page │
+│ │
+│ 2. COMPLETION = EVIDENCE, NOT AESTHETICS │
+│ Stop when queries yield no new facts, not when it looks good │
+│ │
+│ 3. SEPARATE INFORMATION FROM GENERATION │
+│ Get facts first → make it pretty second │
+│ (Otherwise you're polishing hallucinations) │
+│ │
+│ 4. ISOLATE SUB-AGENT CONTEXTS │
+│ Each needs complete standalone instructions │
+│ │
+│ 5. DEDUPLICATE BY URL │
+│ Same source cited differently = noise │
+│ │
+│ 6. CAP ITERATIONS (8 max) AND CONCURRENCY (3 agents) │
+│ Predictable costs (~$0.06/run), prevents runaway │
+│ │
+│ 7. COMPRESS FINDINGS, PRESERVE EVERYTHING │
+│ Never summarize research - you lose signal │
+│ │
+└────────────────────────────────────────────────────────────────────┘
+```
+
+### Speaker Notes
+"Seven takeaways:
+
+1. Start with a draft - even rough, it shows gaps faster than staring at blank page.
+
+2. Completion is about evidence, not aesthetics. Stop when diverse queries find nothing new.
+
+3. Information first, generation second. If you polish while researching, you might be polishing hallucinations.
+
+4. Isolate sub-agent contexts. They can't see each other - give each complete instructions.
+
+5. Deduplicate by URL before synthesis.
+
+6. Set limits - 8 supervisor iterations max, 3 concurrent agents max. Predictable costs (~$0.06/run).
+
+7. When compressing research, never summarize - preserve everything. Just remove duplicates."
+
+---
+
+## SLIDE 12: Resources + Q&A
+**Duration:** 15+ minutes
+
+### Visual
+```
+┌────────────────────────────────────────────────────────────────────┐
+│ │
+│ Questions? │
+│ │
+│ ─────────────────────────────────────────────────────────────── │
+│ │
+│ Go Deeper: │
+│ │
+│ 📝 Blog (full code walkthrough): │
+│ addcommitpush.io/blog/diffusion-deep-research │
+│ │
+│ 💻 Reference Implementation: │
+│ github.com/thinkdepthai/Deep_Research │
+│ │
+│ 🎓 STORM (Stanford): │
+│ github.com/stanford-oval/storm │
+│ │
+│ 📊 Leaderboard: │
+│ huggingface.co/spaces/muset-ai/DeepResearch-Bench-Leaderboard │
+│ │
+│ ─────────────────────────────────────────────────────────────── │
+│ │
+│ Emil Wåreus │
+│ addcommitpush.io | @emilwareus │
+│ │
+│ 🍕 Pizza time! │
+│ │
+└────────────────────────────────────────────────────────────────────┘
+```
+
+### Speaker Notes
+"Questions?
+
+[If needed, prompt with:]
+- What research tasks would you want to automate?
+- Anyone tried the commercial products?
+- What concerns do you have about automated research?
+
+[After Q&A:]
+The code is all open source - try it yourself. My blog has a deep code walkthrough.
+
+Thanks everyone! There's pizza - let's chat!"
+
+---
+
+# TIMING SUMMARY
+
+| Slide | Content | Duration |
+|-------|---------|----------|
+| 1 | Title + Hook | 2 min |
+| 2 | Timeline | 5 min |
+| 3 | STORM Architecture | 4 min |
+| 4 | STORM Demo | 6 min |
+| 5 | Problem with Linear | 2 min |
+| 6 | Diffusion Insight | 3 min |
+| 7 | Diffusion Architecture | 4 min |
+| 8 | Parallel Sub-Agents | 2 min |
+| 9 | Diffusion Demo | 7 min |
+| 10 | Why It Wins + Benchmarks | 3 min |
+| 11 | Practical Takeaways | 3 min |
+| 12 | Resources + Q&A | 15+ min |
+| **TOTAL** | **12 slides** | **~56 min + Q&A** |
+
+---
+
+# VISUAL ASSETS
+
+**From blog components:**
+- `diffusion-overview.tsx` - 4-phase pipeline
+- `parallel-agents.tsx` - Sub-agent architecture
+- `race-metrics.tsx` - Benchmark bars
+
+**Cover image:**
+- `/public/posts/diffusion-deep-research/cover-optimized.webp`
+
+**Demo commands:**
+- `uv run main.py --agent=react "I am giving a presentation at Foo Café in Malmö..."`
+- `uv run main.py --agent=storm "I am giving a presentation at Foo Café in Malmö..."`
+- `uv run main.py --agent=diffusion "I am giving a presentation at Foo Café in Malmö..."`
diff --git a/presentations/deep-research/website-plan.md b/presentations/deep-research/website-plan.md
new file mode 100644
index 0000000..73eb719
--- /dev/null
+++ b/presentations/deep-research/website-plan.md
@@ -0,0 +1,874 @@
+# Deep Research Agents - Interactive Web Presentation
+
+## Concept
+
+A storytelling-driven web presentation that flows like a narrative. Each "page" is a full-screen section you navigate through. The story arc:
+
+**Setup** → **Problem** → **Solution 1 (STORM)** → **Demo** → **Limitation** → **Solution 2 (Diffusion)** → **Demo** → **Why it works** → **Takeaways** → **Resources**
+
+---
+
+## Technical Approach
+
+- Single page app with scroll/keyboard navigation
+- Each section is viewport height (100vh)
+- Smooth transitions between sections
+- Embedded terminal for live demos
+- Reuse animation components from blog (`/components/animations/diffusion/`)
+- Progress indicator showing current position
+
+---
+
+## Page-by-Page Plan
+
+---
+
+### PAGE 1: Title / Landing
+
+**Purpose:** Set the stage, create intrigue
+
+**Story beat:** "You're about to learn something that changes how AI does research"
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ │
+│ │
+│ │
+│ │
+│ DEEP RESEARCH AGENTS │
+│ ───────────────────────── │
+│ Architecture Walkthrough │
+│ │
+│ │
+│ │
+│ │
+│ Emil Wåreus │
+│ Foo Cafe Malmö • 2026 │
+│ │
+│ │
+│ │
+│ │
+│ ↓ scroll or press space │
+│ │
+└─────────────────────────────────────────────────────────────────────────────┘
+```
+
+**Elements:**
+- Large typography, minimal design
+- Subtle animated background (maybe flowing particles or gradient)
+- Cover image faded in background
+- Keyboard hint at bottom
+
+---
+
+### PAGE 2: The Hook - The Group Project
+
+**Purpose:** Create recognition, establish the problem emotionally
+
+**Story beat:** "Remember this pain? AI has the same problem."
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ │
+│ Remember group projects? │
+│ │
+│ ┌─────────────────────────────────────────────────────────────────┐ │
+│ │ │ │
+│ │ 👤 Anna 👤 Bob 👤 Carol 👤 Dan │ │
+│ │ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │ │
+│ │ │Intro │ │History│ │Theory│ │Concl.│ │ │
+│ │ └──┬───┘ └──┬───┘ └──┬───┘ └──┬───┘ │ │
+│ │ │ │ │ │ │ │
+│ │ └─────────────┴──────────────┴─────────────┘ │ │
+│ │ │ │ │
+│ │ ▼ │ │
+│ │ ┌──────────────┐ │ │
+│ │ │ "The Report" │ │ │
+│ │ │ 3hrs before │ │ │
+│ │ │ deadline │ │ │
+│ │ └──────────────┘ │ │
+│ │ │ │
+│ └─────────────────────────────────────────────────────────────────┘ │
+│ │
+│ Everyone writes alone. Then you "glue it together." │
+│ │
+└─────────────────────────────────────────────────────────────────────────────┘
+```
+
+**Elements:**
+- Animated diagram showing isolated work → merge
+- Relatable, slightly humorous tone
+- Pause before revealing the connection
+
+---
+
+### PAGE 3: The Result
+
+**Purpose:** Name the pain explicitly
+
+**Story beat:** "The result was always bad. Here's why."
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ │
+│ │
+│ The result? │
+│ │
+│ │
+│ │
+│ ╭─────────────────────────────╮ │
+│ │ │ │
+│ │ ✗ Repetitive │ │
+│ │ │ │
+│ │ ✗ Inconsistent │ ← appears │
+│ │ │ one by one │
+│ │ ✗ Different tones │ │
+│ │ │ │
+│ │ ✗ Varying quality │ │
+│ │ │ │
+│ │ ✗ Not the grade │ │
+│ │ you wanted │ │
+│ │ │ │
+│ ╰─────────────────────────────╯ │
+│ │
+│ │
+│ │
+└─────────────────────────────────────────────────────────────────────────────┘
+```
+
+**Elements:**
+- Items fade in sequentially (staggered animation)
+- Clean, stark presentation
+- Let it sink in before next page
+
+---
+
+### PAGE 4: The Reveal
+
+**Purpose:** Connect to AI, pivot to the technical content
+
+**Story beat:** "This is exactly how AI research agents work today."
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ │
+│ │
+│ This is exactly how most AI research agents work. │
+│ │
+│ │
+│ ┌─────────────────────────────────────────────────────────────────┐ │
+│ │ │ │
+│ │ ┌────────┐ ┌─────────────────┐ ┌──────────┐ │ │
+│ │ │ │ │ │ │ │ │ │
+│ │ │ PLAN │───────▶│ PARALLEL SEARCH │──────▶│ MERGE │ │ │
+│ │ │ │ │ │ │ │ │ │
+│ │ └────────┘ └─────────────────┘ └──────────┘ │ │
+│ │ │ │ │ │ │
+│ │ ▼ ▼ ▼ │ │
+│ │ Can't see each other │ │
+│ │ Can't update the plan │ │
+│ │ One shot - hope it works │ │
+│ │ │ │
+│ └─────────────────────────────────────────────────────────────────┘ │
+│ │
+│ │
+│ Today: How we fixed this. │
+│ │
+│ │
+└─────────────────────────────────────────────────────────────────────────────┘
+```
+
+**Elements:**
+- Animated pipeline diagram
+- Problems appear below with red/warning styling
+- "Today: How we fixed this" appears last as hook
+
+---
+
+### PAGE 5: Timeline
+
+**Purpose:** Historical context, show evolution
+
+**Story beat:** "This field evolved fast. Here's the journey."
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ │
+│ The Evolution of Research Agents │
+│ │
+│ ════════════════════════════════════════════════════════════════════ │
+│ 2022 2023 2024 2025 │
+│ ════════════════════════════════════════════════════════════════════ │
+│ │ │ │ │ │
+│ │ │ │ │ │
+│ ▼ ▼ ▼ ▼ │
+│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
+│ │Chain │ │ GPT │ │STORM │ │Diffu-│ │
+│ │ of │ │Resea-│ │ │ │ sion │ │
+│ │Thought│ │rcher │ │ ⭐ │ │ ⭐ │ │
+│ └──────┘ └──────┘ └──────┘ └──────┘ │
+│ │ │ │ │ │
+│ │ │ │ │ │
+│ "Show "Open "Multiple "Iterative │
+│ your source perspectives" refinement" │
+│ work" agents" │
+│ │
+│ ──────────────────────────────────────────────────────────────────── │
+│ Single calls → Agents → Multi-agent → Iterative │
+│ ──────────────────────────────────────────────────────────────────── │
+│ │
+└─────────────────────────────────────────────────────────────────────────────┘
+```
+
+**Elements:**
+- Interactive timeline (click/hover for details)
+- Two stars indicate what we'll demo
+- Bottom shows the evolution pattern
+- Timeline animates left-to-right on entry
+
+---
+
+### PAGE 6: STORM Introduction
+
+**Purpose:** Introduce first architecture
+
+**Story beat:** "STORM's insight: simulate expert conversations"
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ │
+│ │
+│ STORM Stanford 2024 │
+│ ══════ │
+│ │
+│ "What if we simulated conversations between experts?" │
+│ │
+│ │
+│ ┌─────────────────────────────────────────────────────┐ │
+│ │ │ │
+│ │ 🔬 Security 👩💻 DevOps 📊 Platform │ │
+│ │ Architect Engineer Specialist │ │
+│ │ │ │
+│ │ "What about "How does "What's the │ │
+│ │ isolation?" deployment GCP story?" │ │
+│ │ work?" │ │
+│ │ │ │
+│ │ Different experts ask different questions │ │
+│ │ → comprehensive coverage │ │
+│ │ │ │
+│ └─────────────────────────────────────────────────────┘ │
+│ │
+│ │
+│ │
+└─────────────────────────────────────────────────────────────────────────────┘
+```
+
+**Elements:**
+- Expert personas with icons
+- Speech bubbles showing different questions
+- Clean, educational layout
+- Stanford attribution in corner
+
+---
+
+### PAGE 7: STORM Architecture
+
+**Purpose:** Show the four phases
+
+**Story beat:** "Four phases: Discover, Converse, Analyze, Synthesize"
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ │
+│ STORM: Four Phases │
+│ │
+│ ┌───────────────────────────────────────────────────────────────────┐ │
+│ │ │ │
+│ │ ┌─────────────┐ │ │
+│ │ │ 1. DISCOVER │ Survey topic → Generate 3-6 expert perspectives │ │
+│ │ └──────┬──────┘ │ │
+│ │ │ │ │
+│ │ ▼ │ │
+│ │ ┌─────────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
+│ │ │ 2. CONVERSE │ │Expert A │ │Expert B │ │Expert C │ parallel │ │
+│ │ └──────┬──────┘ └────┬────┘ └────┬────┘ └────┬────┘ │ │
+│ │ │ └───────────┴───────────┘ │ │
+│ │ ▼ │ │
+│ │ ┌─────────────┐ │ │
+│ │ │ 3. ANALYZE │ Extract facts, find contradictions, fill gaps │ │
+│ │ └──────┬──────┘ │ │
+│ │ │ │ │
+│ │ ▼ │ │
+│ │ ┌─────────────┐ │ │
+│ │ │4. SYNTHESIZE│ Draft outline → Refine → Final article │ │
+│ │ └─────────────┘ │ │
+│ │ │ │
+│ └───────────────────────────────────────────────────────────────────┘ │
+│ │
+└─────────────────────────────────────────────────────────────────────────────┘
+```
+
+**Elements:**
+- Animated flow diagram (phases highlight sequentially)
+- Parallel conversations visually branch out
+- Clean, technical but accessible
+
+---
+
+### PAGE 8: STORM Demo
+
+**Purpose:** Show it working
+
+**Story beat:** "Let me show you this in action."
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ │
+│ Live Demo: STORM │
+│ │
+│ ┌───────────────────────────────────────────────────────────────────┐ │
+│ │ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ │ │
+│ │ $ ./research │ │
+│ │ research> /storm "What are the security implications of │ │
+│ │ WebAssembly for sandboxed execution?" │ │
+│ │ │ │
+│ │ ▌ │ │
+│ │ │ │
+│ │ │ │
+│ │ │ │
+│ │ │ │
+│ │ │ │
+│ │ │ │
+│ │ │ │
+│ │ │ │
+│ │ │ │
+│ │ │ │
+│ │ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ │ │
+│ └───────────────────────────────────────────────────────────────────┘ │
+│ │
+│ Watch: Perspectives → Parallel conversations → Final synthesis │
+│ │
+└─────────────────────────────────────────────────────────────────────────────┘
+```
+
+**Elements:**
+- Full-width terminal embed
+- Dark terminal theme
+- Instruction below for what to watch
+- Could be embedded xterm.js or video if live isn't possible
+
+---
+
+### PAGE 9: The Limitation
+
+**Purpose:** Create tension, set up diffusion
+
+**Story beat:** "But STORM still has a problem..."
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ │
+│ │
+│ │
+│ But there's still a problem... │
+│ │
+│ │
+│ │
+│ ┌─────────────────────────────────────────────────────┐ │
+│ │ │ │
+│ │ ┌───────┐ ┌───────┐ ┌───────┐ │ │
+│ │ │Agent A│ │Agent B│ │Agent C│ │ │
+│ │ └───┬───┘ └───┬───┘ └───┬───┘ │ │
+│ │ │ │ │ │ │
+│ │ ▼ ▼ ▼ │ │
+│ │ ╔═══════════════════════════════╗ │ │
+│ │ ║ Still can't see each other ║ │ │
+│ │ ║ Still one pass ║ │ │
+│ │ ║ Still no self-correction ║ │ │
+│ │ ╚═══════════════════════════════╝ │ │
+│ │ │ │
+│ └─────────────────────────────────────────────────────┘ │
+│ │
+│ │
+│ What if the report could evolve? │
+│ │
+│ │
+└─────────────────────────────────────────────────────────────────────────────┘
+```
+
+**Elements:**
+- Dramatic pause/transition
+- Problems highlighted in warning box
+- Final question creates anticipation
+
+---
+
+### PAGE 10: The Diffusion Insight
+
+**Purpose:** Introduce the breakthrough concept
+
+**Story beat:** "What if research worked like image generation?"
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ │
+│ What if research worked like image generation? │
+│ │
+│ │
+│ ┌─────────────────────────────────────────────────────────────────┐ │
+│ │ IMAGE DIFFUSION │ │
+│ │ │ │
+│ │ ▓▓▓▓▓▓▓ ░▓▓░▓░▓ ░░▓░░░░ ┌──────┐ │ │
+│ │ ▓▓▓▓▓▓▓ → ▓░▓▓▓░▓ → ░░▓▓▓░░ → │ 🖼️ │ │ │
+│ │ ▓▓▓▓▓▓▓ ░▓░▓▓░░ ░░░░▓░░ └──────┘ │ │
+│ │ noise less noise shape clean │ │
+│ └─────────────────────────────────────────────────────────────────┘ │
+│ │
+│ ↕ same idea │
+│ │
+│ ┌─────────────────────────────────────────────────────────────────┐ │
+│ │ RESEARCH DIFFUSION │ │
+│ │ │ │
+│ │ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │ │
+│ │ │Rough │ → │ +Gap │ → │Refine│ → │Final │ │ │
+│ │ │Draft │ │ Fill │ │ │ │Report│ │ │
+│ │ └──────┘ └──────┘ └──────┘ └──────┘ │ │
+│ │ "noise" research denoise clean │ │
+│ └─────────────────────────────────────────────────────────────────┘ │
+│ │
+│ The initial draft IS the noise we refine away. │
+│ │
+└─────────────────────────────────────────────────────────────────────────────┘
+```
+
+**Elements:**
+- Side-by-side animated comparison
+- Visual noise → clean transformation
+- Analogy made explicit
+- Key insight highlighted at bottom
+
+---
+
+### PAGE 11: Diffusion Architecture
+
+**Purpose:** Show the four phases + the critical insight
+
+**Story beat:** "Four phases, but the loop is where magic happens"
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ │
+│ Diffusion Deep Research Google 2025 │
+│ │
+│ ┌───────────────────────────────────────────────────────────────────┐ │
+│ │ │ │
+│ │ ┌────────────────────────────────────────────────────────────┐ │ │
+│ │ │ 1. BRIEF │ Transform query → research objectives │ │ │
+│ │ └─────────────────────────────────────────────────────────────┘ │ │
+│ │ │ │ │
+│ │ ▼ │ │
+│ │ ┌─────────────────────────────────────────────────────────────┐ │ │
+│ │ │ 2. DRAFT │ Generate from LLM knowledge ONLY (the noise)│ │ │
+│ │ └─────────────────────────────────────────────────────────────┘ │ │
+│ │ │ │ │
+│ │ ▼ │ │
+│ │ ╔═════════════════════════════════════════════════════════════╗ │ │
+│ │ ║ 3. LOOP ⭐ │ Repeat: ║ │ │
+│ │ ║ │ → Find gaps ║ │ │
+│ │ ║ │ → Parallel research ║ │ │
+│ │ ║ │ → Refine draft ║ │ │
+│ │ ║ │ → Check: FINDINGS complete? ║ │ │
+│ │ ╚═════════════════════════════════════════════════════════════╝ │ │
+│ │ │ │ │
+│ │ ▼ │ │
+│ │ ┌─────────────────────────────────────────────────────────────┐ │ │
+│ │ │ 4. FINAL │ Apply quality rules, polish │ │ │
+│ │ └─────────────────────────────────────────────────────────────┘ │ │
+│ │ │ │
+│ └───────────────────────────────────────────────────────────────────┘ │
+│ │
+│ ⚠️ Loop stops when EVIDENCE is complete, not when draft looks good │
+│ │
+└─────────────────────────────────────────────────────────────────────────────┘
+```
+
+**Elements:**
+- Loop phase highlighted/boxed differently
+- Warning callout at bottom (critical insight)
+- Reuse `diffusion-overview` component with modifications
+
+---
+
+### PAGE 12: The Loop Visualized
+
+**Purpose:** Show the iterative refinement
+
+**Story beat:** "Watch the draft evolve through iterations"
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ │
+│ The Draft Evolves │
+│ │
+│ ┌─────────────────────────────────────────────────────────────────┐ │
+│ │ │ │
+│ │ Iteration 1 Iteration 5 │ │
+│ │ ──────────── ──────────── │ │
+│ │ │ │
+│ │ • Topic overview [GAP] WebAssembly provides │ │
+│ │ • Security unclear sandboxing via linear │ │
+│ │ • Need to research memory model. Key │ │
+│ │ isolation mechanisms mechanisms include: [1] │ │
+│ │ • Performance vs security - Memory bounds checking │ │
+│ │ tradeoffs [MISSING] - Capability-based model │ │
+│ │ Performance overhead: │ │
+│ │ 5-10% vs native [2][3] │ │
+│ │ │ │
+│ │ ─────────────▶ │ │
+│ │ iterations │ │
+│ │ 2, 3, 4... │ │
+│ │ │ │
+│ └─────────────────────────────────────────────────────────────────┘ │
+│ │
+│ [INTERACTIVE: Slider to scrub through iterations 1-10] │
+│ ════════════════════●══════════════════════════════════ │
+│ 5 │
+│ │
+└─────────────────────────────────────────────────────────────────────────────┘
+```
+
+**Elements:**
+- Reuse `draft-denoising` component
+- Interactive slider to show progression
+- Clear before/after comparison
+- GAPs get filled with citations
+
+---
+
+### PAGE 13: Parallel Sub-Agents
+
+**Purpose:** Explain the isolation pattern
+
+**Story beat:** "Sub-agents work in parallel but isolated - that's a feature"
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ │
+│ Parallel Research, Isolated Contexts │
+│ │
+│ ┌───────────────────────────────────────────────────────────────────┐ │
+│ │ │ │
+│ │ ┌──────────────────┐ │ │
+│ │ │ SUPERVISOR │ │ │
+│ │ │ "Research X, Y" │ │ │
+│ │ └────────┬─────────┘ │ │
+│ │ │ │ │
+│ │ ┌────────────────┼────────────────┐ │ │
+│ │ │ │ │ │ │
+│ │ ▼ ▼ ▼ │ │
+│ │ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ │
+│ │ │ Sub-Agent │ │ Sub-Agent │ │ Sub-Agent │ │ │
+│ │ │ 🔒 │ │ 🔒 │ │ 🔒 │ │ │
+│ │ │ Topic A │ │ Topic B │ │ Topic C │ │ │
+│ │ │ │ │ │ │ │ │ │
+│ │ │ Can't see │ │ Can't see │ │ Can't see │ │ │
+│ │ │ B or C │ │ A or C │ │ A or B │ │ │
+│ │ └─────┬──────┘ └─────┬──────┘ └─────┬──────┘ │ │
+│ │ │ │ │ │ │
+│ │ └───────────────┼───────────────┘ │ │
+│ │ ▼ │ │
+│ │ ┌──────────────────┐ │ │
+│ │ │ SUPERVISOR │ │ │
+│ │ │ Merges, Refines │ │ │
+│ │ └──────────────────┘ │ │
+│ │ │ │
+│ └───────────────────────────────────────────────────────────────────┘ │
+│ │
+│ Why isolated? Independent perspectives. No cross-contamination. │
+│ │
+└─────────────────────────────────────────────────────────────────────────────┘
+```
+
+**Elements:**
+- Reuse `parallel-agents` component
+- Lock icons to emphasize isolation
+- Clear supervisor → agents → supervisor flow
+- Explanation at bottom
+
+---
+
+### PAGE 14: Diffusion Demo
+
+**Purpose:** Show it working, compare to STORM
+
+**Story beat:** "Watch the iteration count. See the draft evolve."
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ │
+│ Live Demo: Diffusion │
+│ │
+│ ┌───────────────────────────────────────────────────────────────────┐ │
+│ │ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ │ │
+│ │ research> /think_deep "Compare STORM and Diffusion research │ │
+│ │ architectures" │ │
+│ │ │ │
+│ │ ▌ │ │
+│ │ │ │
+│ │ │ │
+│ │ │ │
+│ │ │ │
+│ │ │ │
+│ │ │ │
+│ │ │ │
+│ │ │ │
+│ │ │ │
+│ │ │ │
+│ │ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ │ │
+│ └───────────────────────────────────────────────────────────────────┘ │
+│ │
+│ Watch: Initial draft → Gap detection → Iterations → Final report │
+│ │
+└─────────────────────────────────────────────────────────────────────────────┘
+```
+
+**Elements:**
+- Same terminal style as STORM demo
+- Different command (/think_deep)
+- Instruction emphasizes what's different to watch
+
+---
+
+### PAGE 15: Why It Wins
+
+**Purpose:** Show the evidence
+
+**Story beat:** "74.5% win rate. Here's why."
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ │
+│ The Results │
+│ │
+│ ┌───────────────────────────────────────────────────────────────────┐ │
+│ │ │ │
+│ │ Google Diffusion vs OpenAI Deep Research │ │
+│ │ │ │
+│ │ ╔═══════════════════════╗ │ │
+│ │ ║ ║ │ │
+│ │ ║ 74.5% WIN RATE ║ │ │
+│ │ ║ ║ │ │
+│ │ ╚═══════════════════════╝ │ │
+│ │ │ │
+│ └───────────────────────────────────────────────────────────────────┘ │
+│ │
+│ Why? │
+│ ┌────────────────────────────┬────────────────────────────────────┐ │
+│ │ Iterative refinement │ Catches gaps single-pass misses │ │
+│ │ Evidence-based completion │ Stops when facts found, not polish │ │
+│ │ Self-balancing │ 2 iters for simple, 15 for complex │ │
+│ │ Draft as anchor │ Coherence across iterations │ │
+│ │ Isolated sub-agents │ Independent perspectives │ │
+│ └────────────────────────────┴────────────────────────────────────┘ │
+│ │
+│ Iteration + Self-correction > Single pass │
+│ │
+└─────────────────────────────────────────────────────────────────────────────┘
+```
+
+**Elements:**
+- Big win rate number (animated count-up)
+- Clean table of reasons
+- Reuse `race-metrics` component if showing full benchmarks
+- Key insight at bottom
+
+---
+
+### PAGE 16: Takeaways
+
+**Purpose:** Actionable lessons
+
+**Story beat:** "Seven things you can apply today."
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ │
+│ What You Can Apply Today │
+│ │
+│ ┌───────────────────────────────────────────────────────────────────┐ │
+│ │ │ │
+│ │ 1 Start with a draft │ │
+│ │ Even rough - reveals gaps faster than blank page │ │
+│ │ │ │
+│ │ 2 Completion = evidence, not aesthetics │ │
+│ │ Stop when queries yield no new facts │ │
+│ │ │ │
+│ │ 3 Information first, generation second │ │
+│ │ Don't polish hallucinations │ │
+│ │ │ │
+│ │ 4 Isolate sub-agent contexts │ │
+│ │ Each needs complete standalone instructions │ │
+│ │ │ │
+│ │ 5 Deduplicate by URL │ │
+│ │ │ │
+│ │ 6 Cap iterations (15) and concurrency (3) │ │
+│ │ │ │
+│ │ 7 Compress findings, preserve everything │ │
+│ │ │ │
+│ └───────────────────────────────────────────────────────────────────┘ │
+│ │
+│ │
+└─────────────────────────────────────────────────────────────────────────────┘
+```
+
+**Elements:**
+- Clean numbered list
+- Each item fades in sequentially
+- Most important items (1-3) have descriptions
+- Rest are concise
+
+---
+
+### PAGE 17: Resources + Questions
+
+**Purpose:** Close, provide next steps, open Q&A
+
+**Story beat:** "Go deeper. Let's discuss."
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ │
+│ │
+│ Questions? │
+│ │
+│ │
+│ ───────────────────────────────────────────────────────────────────── │
+│ │
+│ Go Deeper │
+│ │
+│ 📝 Blog post (code walkthrough) │
+│ addcommitpush.io/blog/diffusion-deep-research │
+│ │
+│ 💻 My Go implementation │
+│ github.com/emilwareus/addcommitpush.io/go-research │
+│ │
+│ 🎓 STORM (Stanford) │
+│ github.com/stanford-oval/storm │
+│ │
+│ 📊 Leaderboard │
+│ huggingface.co/spaces/muset-ai/DeepResearch-Bench-Leaderboard │
+│ │
+│ ───────────────────────────────────────────────────────────────────── │
+│ │
+│ Emil Wåreus │
+│ addcommitpush.io │
+│ │
+│ 🍕 Pizza! │
+│ │
+└─────────────────────────────────────────────────────────────────────────────┘
+```
+
+**Elements:**
+- Clean, minimal
+- Links are clickable
+- QR codes could be added for mobile
+- Pizza emoji for Foo Cafe tradition
+
+---
+
+## Navigation & UX
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ │
+│ Navigation Bar (fixed, semi-transparent) │
+│ ┌─────────────────────────────────────────────────────────────────────┐ │
+│ │ Deep Research Agents ● ● ● ● ○ ○ ○ ○ ○ ○ ○ ○ 5/17 │ │
+│ └─────────────────────────────────────────────────────────────────────┘ │
+│ │
+│ Controls: │
+│ - Arrow keys / Space: Navigate │
+│ - Scroll: Navigate │
+│ - Click dots: Jump to page │
+│ - ESC: Show overview/grid │
+│ │
+└─────────────────────────────────────────────────────────────────────────────┘
+```
+
+---
+
+## Technical Components Needed
+
+1. **PageContainer** - Full viewport section with transitions
+2. **NavigationBar** - Progress dots, keyboard hints
+3. **Terminal** - For live demos (xterm.js or video fallback)
+4. **AnimatedDiagram** - Reusable animated flow diagrams
+5. **Timeline** - Interactive timeline component
+6. **ComparisonSlider** - For iteration scrubbing
+
+**Reuse from blog:**
+- `DiffusionOverview`
+- `DraftDenoising`
+- `ParallelAgents`
+- `TwoStageGap`
+- `RACEMetrics`
+
+---
+
+## Page Summary
+
+| # | Page | Purpose | Duration |
+|---|------|---------|----------|
+| 1 | Title | Set the stage | 30s |
+| 2 | Group Project | Emotional hook | 1m |
+| 3 | The Result | Name the pain | 30s |
+| 4 | The Reveal | Connect to AI | 1m |
+| 5 | Timeline | Context | 3m |
+| 6 | STORM Intro | First solution | 2m |
+| 7 | STORM Architecture | How it works | 2m |
+| 8 | STORM Demo | See it work | 5m |
+| 9 | The Limitation | Create tension | 1m |
+| 10 | Diffusion Insight | Breakthrough | 2m |
+| 11 | Diffusion Architecture | How it works | 2m |
+| 12 | Loop Visualized | Show evolution | 2m |
+| 13 | Parallel Agents | Key pattern | 1m |
+| 14 | Diffusion Demo | See it work | 6m |
+| 15 | Why It Wins | Evidence | 2m |
+| 16 | Takeaways | Actionable | 2m |
+| 17 | Resources + Q&A | Close | 15m+ |
+
+**Total: 17 pages, ~48 min content + Q&A**
+
+---
+
+## File Structure for Implementation
+
+```
+app/presentations/deep-research/
+├── page.tsx # Main presentation page
+├── components/
+│ ├── PageContainer.tsx # Full-screen section wrapper
+│ ├── NavigationBar.tsx # Progress indicator
+│ ├── Terminal.tsx # Demo terminal
+│ ├── pages/
+│ │ ├── TitlePage.tsx
+│ │ ├── GroupProjectPage.tsx
+│ │ ├── ResultPage.tsx
+│ │ ├── RevealPage.tsx
+│ │ ├── TimelinePage.tsx
+│ │ ├── StormIntroPage.tsx
+│ │ ├── StormArchPage.tsx
+│ │ ├── StormDemoPage.tsx
+│ │ ├── LimitationPage.tsx
+│ │ ├── DiffusionInsightPage.tsx
+│ │ ├── DiffusionArchPage.tsx
+│ │ ├── LoopPage.tsx
+│ │ ├── ParallelAgentsPage.tsx
+│ │ ├── DiffusionDemoPage.tsx
+│ │ ├── WhyItWinsPage.tsx
+│ │ ├── TakeawaysPage.tsx
+│ │ └── ResourcesPage.tsx
+│ └── index.ts
+└── styles/
+ └── presentation.css
+```
diff --git a/public/presentations/deep-research/logos/debricked-logo.png b/public/presentations/deep-research/logos/debricked-logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..ced58a540a9f06a2405606f14d1f367c1ceaf7ef
GIT binary patch
literal 107731
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